use crate::{
dto::fleet_registry::{FleetRegistryVersion, FleetSubnetRootStatus},
ids::{ComponentTopologyDigest, FleetSubnetRootBinding, FleetSubnetRootReleaseSet, SubnetId},
};
use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct FleetSubnetRootAuthority {
pub binding: FleetSubnetRootBinding,
pub initial_release_set: FleetSubnetRootReleaseSet,
pub expected_module_hash: [u8; 32],
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct FleetSubnetRootCanisterSummary {
pub fleet_registry: FleetRegistryVersion,
pub placement_subnet: SubnetId,
pub fleet_subnet_root: Principal,
pub status: FleetSubnetRootStatus,
pub infrastructure_canisters: u32,
pub component_canisters: u32,
pub total_canisters: u32,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct FleetSubnetRootDrainingRequest {
pub operation_id: [u8; 32],
pub expected_registry: FleetRegistryVersion,
}
#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct FleetSubnetRootDrainingStatusRequest {
pub operation_id: [u8; 32],
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct FleetSubnetRootDrainingResponse {
pub operation_id: [u8; 32],
pub fleet_subnet_root: Principal,
pub placement_subnet: SubnetId,
pub active_registry: FleetRegistryVersion,
pub component_topology_digest: ComponentTopologyDigest,
pub active_release_set: FleetSubnetRootReleaseSet,
pub next_allocation_sequence: u64,
pub reserved_component_instances: u32,
pub committed_component_instances: u32,
pub managed_descendants: u32,
pub known_created_component_canisters: u32,
pub root_registry_encoded_bytes: u64,
pub started_at_ns: u64,
}
#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
pub struct FleetSubnetRootInitArgs {
pub authority: FleetSubnetRootAuthority,
pub install_id: [u8; 32],
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ids::{
AppId, CanonicalNetworkId, FleetBinding, FleetCoordinatorBinding, FleetId, FleetKey,
FleetRegistryAuthority,
};
#[test]
fn canister_summary_and_draining_contracts_round_trip_through_candid() {
let summary = FleetSubnetRootCanisterSummary {
fleet_registry: FleetRegistryVersion {
authority: FleetRegistryAuthority {
binding: FleetCoordinatorBinding {
fleet: FleetBinding {
fleet: FleetKey {
canonical_network_id: CanonicalNetworkId::ic_mainnet(),
fleet_id: FleetId::from_generated_bytes([1; 32]),
},
app: AppId::from("toko"),
},
coordinator_subnet: SubnetId::from_principal(Principal::from_slice(
&[2; 29],
)),
coordinator: Principal::from_slice(&[3; 29]),
},
epoch: 1,
},
revision: 4,
content_hash: [5; 32],
},
placement_subnet: SubnetId::from_principal(Principal::from_slice(&[6; 29])),
fleet_subnet_root: Principal::from_slice(&[7; 29]),
status: FleetSubnetRootStatus::Active,
infrastructure_canisters: 2,
component_canisters: 3,
total_canisters: 5,
};
let candid = candid::encode_one(&summary).expect("encode Canister summary");
let decoded: FleetSubnetRootCanisterSummary =
candid::decode_one(&candid).expect("decode Canister summary");
assert_eq!(decoded, summary);
let draining = FleetSubnetRootDrainingResponse {
operation_id: [8; 32],
fleet_subnet_root: summary.fleet_subnet_root,
placement_subnet: summary.placement_subnet,
active_registry: summary.fleet_registry,
component_topology_digest: ComponentTopologyDigest::from_bytes([9; 32]),
active_release_set: FleetSubnetRootReleaseSet {
release_build_id: crate::ids::ReleaseBuildId::from_nonce(
crate::ids::ReleaseBuildNonce::from_random_bytes([10; 32]),
),
manifest_digest: crate::ids::ReleaseSetDigest::from_bytes([11; 32]),
},
next_allocation_sequence: 12,
reserved_component_instances: 13,
committed_component_instances: 14,
managed_descendants: 15,
known_created_component_canisters: 16,
root_registry_encoded_bytes: 17_000,
started_at_ns: 18,
};
let request = FleetSubnetRootDrainingRequest {
operation_id: draining.operation_id,
expected_registry: draining.active_registry.clone(),
};
let status = FleetSubnetRootDrainingStatusRequest {
operation_id: draining.operation_id,
};
let request_bytes = candid::encode_one(&request).expect("encode root draining request");
let status_bytes = candid::encode_one(status).expect("encode root draining status");
let response_bytes = candid::encode_one(&draining).expect("encode root draining response");
assert_eq!(
candid::decode_one::<FleetSubnetRootDrainingRequest>(&request_bytes)
.expect("decode root draining request"),
request
);
assert_eq!(
candid::decode_one::<FleetSubnetRootDrainingStatusRequest>(&status_bytes)
.expect("decode root draining status"),
status
);
assert_eq!(
candid::decode_one::<FleetSubnetRootDrainingResponse>(&response_bytes)
.expect("decode root draining response"),
draining
);
}
}