canic_backup/plan/build/
mod.rs1mod phases;
8mod selector;
9mod targets;
10
11pub use selector::resolve_backup_selector;
12
13use crate::plan::{
14 BackupPlan, BackupPlanError, BackupScopeKind, ControlAuthority, ControlAuthoritySource,
15 QuiescencePolicy, SnapshotReadAuthority,
16};
17use crate::{manifest::IdentityMode, registry::RegistryEntry};
18use phases::build_backup_phases;
19use targets::{backup_target, selected_subtree_root, snapshot_targets, target_depths};
20
21pub struct BackupPlanBuildInput<'a> {
29 pub plan_id: String,
30 pub run_id: String,
31 pub fleet: String,
32 pub network: String,
33 pub root_canister_id: String,
34 pub selected_canister_id: Option<String>,
35 pub selected_scope_kind: BackupScopeKind,
36 pub include_descendants: bool,
37 pub topology_hash_before_quiesce: String,
38 pub registry: &'a [RegistryEntry],
39 pub control_authority: ControlAuthority,
40 pub snapshot_read_authority: SnapshotReadAuthority,
41 pub quiescence_policy: QuiescencePolicy,
42 pub identity_mode: IdentityMode,
43}
44
45pub fn build_backup_plan(input: BackupPlanBuildInput<'_>) -> Result<BackupPlan, BackupPlanError> {
47 let snapshot_read_authority = input.snapshot_read_authority.clone();
48 let quiescence_policy = input.quiescence_policy.clone();
49 let root_included = input.selected_scope_kind == BackupScopeKind::MaintenanceRoot;
50 let selected_subtree_root = selected_subtree_root(&input)?;
51 let snapshot_targets = snapshot_targets(&input)?;
52 let target_depths = target_depths(input.registry);
53 let targets = snapshot_targets
54 .into_iter()
55 .map(|target| {
56 backup_target(
57 target,
58 &target_depths,
59 input.control_authority.clone(),
60 input.snapshot_read_authority.clone(),
61 input.identity_mode.clone(),
62 )
63 })
64 .collect::<Vec<_>>();
65 let phases = build_backup_phases(&targets);
66
67 let plan = BackupPlan {
68 plan_id: input.plan_id,
69 run_id: input.run_id,
70 fleet: input.fleet,
71 network: input.network,
72 root_canister_id: input.root_canister_id,
73 selected_subtree_root,
74 selected_scope_kind: input.selected_scope_kind,
75 include_descendants: input.include_descendants,
76 root_included,
77 requires_root_controller: input.control_authority.source
78 == ControlAuthoritySource::RootController,
79 snapshot_read_authority,
80 quiescence_policy,
81 topology_hash_before_quiesce: input.topology_hash_before_quiesce,
82 targets,
83 phases,
84 };
85 plan.validate()?;
86 Ok(plan)
87}