Add local CAS file roots
This commit is contained in:
parent
64e17ff957
commit
e1f36ffafb
12 changed files with 581 additions and 13 deletions
|
|
@ -1,7 +1,7 @@
|
|||
pub mod service;
|
||||
|
||||
use geth_auth::{AuthExplanation, AuthOp, AuthOpKind};
|
||||
use geth_cas::{LocalCas, hash_path};
|
||||
use geth_cas::{BlobInfoSummary, FileRoot, FileRootScan, LocalCas, hash_path};
|
||||
use geth_config::{GethConfig, GethPaths, RelayMode};
|
||||
use geth_control::{
|
||||
CasBlob, ControlRequest, ControlResponse, KeychainStatusResponse, NodeIdResponse,
|
||||
|
|
@ -23,9 +23,9 @@ use geth_ssh_identity::{
|
|||
cert_request_id, certificate_id, openssh_krl_spec, revocation_id, ssh_public_key_fingerprint,
|
||||
};
|
||||
use geth_store::{
|
||||
Store, StoredAuthOp, StoredDbResource, StoredDocumentResource, StoredKeychainOp, StoredKvEntry,
|
||||
StoredKvStore, StoredResource, StoredResourceSecret, StoredSshCertRequest,
|
||||
StoredSshCertificate, StoredSshRevocation,
|
||||
Store, StoredAuthOp, StoredDbResource, StoredDocumentResource, StoredFileRoot,
|
||||
StoredKeychainOp, StoredKvEntry, StoredKvStore, StoredResource, StoredResourceSecret,
|
||||
StoredSshCertRequest, StoredSshCertificate, StoredSshRevocation,
|
||||
};
|
||||
use geth_types::{
|
||||
AuthOpId, Capability, KeyId, NodeId, PrincipalId, ResourceId, ResourceKind, ResourceName,
|
||||
|
|
@ -344,6 +344,76 @@ pub fn handle_request(
|
|||
.collect::<Result<Vec<_>, NodeError>>()?;
|
||||
Ok(ControlResponse::CasList { blobs })
|
||||
}
|
||||
ControlRequest::CasRootAdd { name, path } => {
|
||||
geth_cas::validate_file_root_name(&name)?;
|
||||
if !path.is_dir() {
|
||||
return Err(NodeError::Cas(geth_cas::CasError::TreeRootNotDirectory(
|
||||
path.display().to_string(),
|
||||
)));
|
||||
}
|
||||
let path = std::fs::canonicalize(path)?;
|
||||
let resource_id = format!("resource:cas-tree:{name}");
|
||||
store.insert_resource(&StoredResource {
|
||||
resource_id: resource_id.clone(),
|
||||
kind: ResourceKind::Cas.to_string(),
|
||||
name: format!("file-root:{name}"),
|
||||
status: "active".to_owned(),
|
||||
})?;
|
||||
let stored = StoredFileRoot {
|
||||
root_id: format!("file-root:{name}"),
|
||||
resource_id,
|
||||
name,
|
||||
path: path.display().to_string(),
|
||||
latest_tree_hash: None,
|
||||
latest_tree_json: None,
|
||||
updated_at_ms: geth_store::now_ms(),
|
||||
};
|
||||
store.upsert_file_root(&stored)?;
|
||||
Ok(ControlResponse::CasRootAdded {
|
||||
root: file_root_from_stored(&stored),
|
||||
})
|
||||
}
|
||||
ControlRequest::CasRootList => Ok(ControlResponse::CasRootList {
|
||||
roots: store
|
||||
.list_file_roots()?
|
||||
.iter()
|
||||
.map(file_root_from_stored)
|
||||
.collect(),
|
||||
}),
|
||||
ControlRequest::CasRootScan { name } => {
|
||||
geth_cas::validate_file_root_name(&name)?;
|
||||
let mut stored = store
|
||||
.get_file_root_by_name(&name)?
|
||||
.ok_or_else(|| NodeError::ResourceNotFound(format!("file-root:{name}")))?;
|
||||
let previous_tree = stored
|
||||
.latest_tree_json
|
||||
.as_deref()
|
||||
.map(serde_json::from_str)
|
||||
.transpose()?;
|
||||
let cas = LocalCas::new(node.paths.cas_dir());
|
||||
let scanned = cas.add_tree_path(Path::new(&stored.path))?;
|
||||
store.record_cas_object(
|
||||
scanned.object.hash.as_str(),
|
||||
scanned.object.size_bytes,
|
||||
&scanned.object.path.to_string_lossy(),
|
||||
)?;
|
||||
let changes = geth_cas::diff_tree_objects(previous_tree.as_ref(), &scanned.tree);
|
||||
stored.latest_tree_hash = Some(scanned.object.hash.to_string());
|
||||
stored.latest_tree_json = Some(serde_json::to_string(&scanned.tree)?);
|
||||
stored.updated_at_ms = geth_store::now_ms();
|
||||
store.upsert_file_root(&stored)?;
|
||||
Ok(ControlResponse::CasRootScanned {
|
||||
scan: FileRootScan {
|
||||
root: file_root_from_stored(&stored),
|
||||
tree: BlobInfoSummary {
|
||||
hash: scanned.object.hash,
|
||||
size_bytes: scanned.object.size_bytes,
|
||||
},
|
||||
changes,
|
||||
note: geth_cas::file_root_scan_note().to_owned(),
|
||||
},
|
||||
})
|
||||
}
|
||||
ControlRequest::KeychainInit { admin_key_path } => {
|
||||
let mut ops = Vec::new();
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
|
|
@ -1055,6 +1125,17 @@ fn document_state_from_stored(stored: &StoredDocumentResource) -> DocumentState
|
|||
}
|
||||
}
|
||||
|
||||
fn file_root_from_stored(stored: &StoredFileRoot) -> FileRoot {
|
||||
FileRoot {
|
||||
id: stored.root_id.clone(),
|
||||
resource: stored.resource_id.clone(),
|
||||
name: stored.name.clone(),
|
||||
path: stored.path.clone(),
|
||||
latest_tree: stored.latest_tree_hash.clone().map(Into::into),
|
||||
updated_at_ms: stored.updated_at_ms,
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_resource_exists(store: &Store, resource_id: &str) -> Result<(), NodeError> {
|
||||
if store
|
||||
.list_resources()?
|
||||
|
|
|
|||
Loading…
Reference in a new issue