Skip to main content

canic_host/component_operation/ops/progress/
mod.rs

1//! Correlate Root operation detail before exposing host progress.
2
3use crate::component_operation::{
4    ComponentOperationError,
5    model::{ComponentPhase, ComponentPlanRecord, ComponentProgressRecord},
6    view::ComponentProgressObservation,
7};
8use canic_control_plane::dto::root::RootComponentOperationStatus;
9use canic_core::dto::component_registry::{
10    ComponentProvisioningOrigin, RootComponentAllocationPhase,
11};
12
13/// Project only a response bound to this exact operation, caller, Spec and release.
14pub fn project_progress(
15    plan: &ComponentPlanRecord,
16    status: RootComponentOperationStatus,
17) -> Result<ComponentProgressObservation, ComponentOperationError> {
18    let allocation = status.allocation;
19    let identity_matches = allocation.operation_id == plan.operation_id
20        && allocation.component_spec == plan.authority.component_spec
21        && allocation.spec_hash == plan.authority.spec_hash
22        && allocation.role == plan.authority.role;
23    let origin = ComponentProvisioningOrigin::FleetAdministrator {
24        caller: plan.authority.operator,
25    };
26    if !identity_matches
27        || allocation.release_set != plan.authority.release_set
28        || allocation.provisioning_origin != origin
29    {
30        return Err(ComponentOperationError::Progress);
31    }
32    let phase = match allocation.phase {
33        RootComponentAllocationPhase::Reserved => ComponentPhase::Reserved,
34        RootComponentAllocationPhase::CreationIntent => ComponentPhase::CreationIntent,
35        RootComponentAllocationPhase::Created => ComponentPhase::Created,
36        RootComponentAllocationPhase::InstallIntent => ComponentPhase::InstallIntent,
37        RootComponentAllocationPhase::Installed => ComponentPhase::Installed,
38        RootComponentAllocationPhase::Verified => ComponentPhase::Verified,
39        RootComponentAllocationPhase::Committed => ComponentPhase::Committed,
40        RootComponentAllocationPhase::Removed => ComponentPhase::Removed,
41    };
42    Ok(ComponentProgressObservation {
43        progress: Some(ComponentProgressRecord {
44            allocation_sequence: allocation.allocation_sequence,
45            component: allocation.component,
46            phase,
47            binding: allocation.installation.map(|evidence| evidence.binding),
48            complete: status.complete,
49        }),
50    })
51}