ic_backup/model/ic_snapshot_upload_observation/
mod.rs1use crate::model::attempt_journal::ObservationReservation;
4use crate::model::{
5 attempt_journal::{AttemptAuthorityRecord, AttemptJournalRecord},
6 ic_observation::IcObservationRequestError,
7 ic_request::{IcManagementMethodRecord, IcManagementRequestRecord},
8 ic_snapshot_upload::{
9 IcSnapshotUploadAttemptError, IcSnapshotUploadKind, IcSnapshotUploadRequest,
10 original_authority,
11 },
12 operation_plan::OperationPlanRecord,
13};
14use thiserror::Error;
15
16#[derive(Debug)]
23pub struct IcSnapshotUploadObservationRequest<'request, 'source> {
24 plan: &'request OperationPlanRecord,
25 mutation: &'request IcSnapshotUploadRequest<'source>,
26 payload: &'request IcManagementRequestRecord,
27 reservation: ObservationReservation,
28}
29
30impl<'request, 'source> IcSnapshotUploadObservationRequest<'request, 'source> {
31 pub fn new(
38 plan: &'request OperationPlanRecord,
39 operation_sequence: u64,
40 journal: &AttemptJournalRecord,
41 mutation: &'request IcSnapshotUploadRequest<'source>,
42 payload: &'request IcManagementRequestRecord,
43 ) -> Result<Self, IcSnapshotUploadObservationError> {
44 if !matches!(mutation.kind(), IcSnapshotUploadKind::Metadata) {
45 return Err(IcSnapshotUploadObservationError::UnsupportedUpload);
46 }
47 if payload.method() != IcManagementMethodRecord::ListCanisterSnapshots {
48 return Err(IcSnapshotUploadObservationError::UnsupportedObservation);
49 }
50 let authority = original_authority(plan, operation_sequence, journal, mutation)?;
51 payload
52 .validate_observation_binding(authority.binding(), &payload.digest())
53 .map_err(IcObservationRequestError::from)?;
54 let reservation = ObservationReservation::new(authority, journal, payload.digest())
55 .map_err(crate::model::ic_observation::IcObservationRequestError::from)?;
56 let request = Self {
57 plan,
58 mutation,
59 payload,
60 reservation,
61 };
62 Ok(request)
63 }
64
65 #[must_use]
67 pub const fn plan(&self) -> &OperationPlanRecord {
68 self.plan
69 }
70 #[must_use]
72 pub const fn mutation(&self) -> &'request IcSnapshotUploadRequest<'source> {
73 self.mutation
74 }
75 #[must_use]
77 pub const fn payload(&self) -> &'request IcManagementRequestRecord {
78 self.payload
79 }
80 #[must_use]
82 pub const fn authority(&self) -> &AttemptAuthorityRecord {
83 &self.reservation.authority
84 }
85 #[must_use]
87 pub const fn mutation_attempt(&self) -> u32 {
88 self.reservation.mutation_attempt
89 }
90 #[must_use]
92 pub const fn observation_attempt(&self) -> u32 {
93 self.reservation.observation_attempt
94 }
95 pub fn validate_journal(
99 &self,
100 journal: &AttemptJournalRecord,
101 ) -> Result<(), IcObservationRequestError> {
102 self.reservation
103 .validate(journal)
104 .map_err(IcObservationRequestError::from)
105 }
106}
107
108#[derive(Debug, Error)]
110pub enum IcSnapshotUploadObservationError {
111 #[error("snapshot upload observation requires metadata intent")]
113 UnsupportedUpload,
114 #[error("snapshot upload observation requires snapshot list")]
116 UnsupportedObservation,
117 #[error(transparent)]
119 Upload(#[from] IcSnapshotUploadAttemptError),
120 #[error(transparent)]
122 Observation(#[from] IcObservationRequestError),
123}
124
125#[cfg(test)]
126mod tests;