ic_backup/policy/local_restore_source/
mod.rs1use crate::{
4 model::{
5 download_journal::DownloadJournalRecord,
6 operation_plan::OperationPlanRecord,
7 restore_safety::{RestoreSafetyRequirementError, RestoreSafetyRequirementRecord},
8 },
9 policy::download_integrity::{
10 self, DownloadIntegrityPolicyError, DurableDownloadArtifactView, DurableDownloadView,
11 },
12};
13use thiserror::Error;
14
15#[derive(Debug)]
20pub struct LocalRestoreSourceView<'a> {
21 restore: &'a OperationPlanRecord,
22 requirement: &'a RestoreSafetyRequirementRecord,
23 source: DurableDownloadView<'a>,
24}
25
26impl<'a> LocalRestoreSourceView<'a> {
27 #[must_use]
29 pub const fn restore(&self) -> &'a OperationPlanRecord {
30 self.restore
31 }
32 #[must_use]
34 pub const fn requirement(&self) -> &'a RestoreSafetyRequirementRecord {
35 self.requirement
36 }
37 #[must_use]
39 pub const fn source(&self) -> &DurableDownloadView<'a> {
40 &self.source
41 }
42 pub fn selected_artifacts(&self) -> impl Iterator<Item = &DurableDownloadArtifactView<'a>> {
44 self.source.artifacts().iter().filter(|artifact| {
45 self.restore
46 .selected_targets()
47 .binary_search_by(|target| target.as_str().cmp(artifact.artifact().canister_id()))
48 .is_ok()
49 })
50 }
51}
52
53pub fn validate<'a>(
63 restore: &'a OperationPlanRecord,
64 source: &'a OperationPlanRecord,
65 requirement: &'a RestoreSafetyRequirementRecord,
66 manifest: &'a DownloadJournalRecord,
67) -> Result<LocalRestoreSourceView<'a>, LocalRestoreSourcePolicyError> {
68 requirement.validate_plans(restore, source)?;
69 if &manifest.digest() != requirement.source_artifacts() {
70 return Err(LocalRestoreSourcePolicyError::ManifestMismatch);
71 }
72 let source = download_integrity::validate(source, manifest)?;
73 Ok(LocalRestoreSourceView {
74 restore,
75 requirement,
76 source,
77 })
78}
79
80#[derive(Debug, Error)]
82pub enum LocalRestoreSourcePolicyError {
83 #[error(transparent)]
85 Requirement(#[from] RestoreSafetyRequirementError),
86 #[error("local restore source manifest mismatch")]
88 ManifestMismatch,
89 #[error(transparent)]
91 Download(#[from] DownloadIntegrityPolicyError),
92}
93
94#[cfg(test)]
95mod tests;