From d397faf1ad2a53e44c50f7749c0690707bc95580 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 17 Nov 2023 11:35:35 +0100 Subject: [PATCH 1/6] feat: delete satellites and orbiters Signed-off-by: David Dal Busco --- src/mission_control/src/lib.rs | 22 +++++++- src/mission_control/src/mgmt/canister.rs | 3 +- src/mission_control/src/segments/canister.rs | 27 ++++++++- src/mission_control/src/segments/orbiter.rs | 19 ++++++- src/mission_control/src/segments/satellite.rs | 24 +++++++- src/mission_control/src/segments/store.rs | 29 +++++++++- src/observatory/src/lib.rs | 3 +- src/observatory/src/store.rs | 2 +- src/orbiter/src/lib.rs | 12 +++- src/satellite/src/lib.rs | 12 +++- src/shared/src/ic.rs | 55 ++++++++++++++++++- src/shared/src/types.rs | 8 ++- 12 files changed, 198 insertions(+), 18 deletions(-) diff --git a/src/mission_control/src/lib.rs b/src/mission_control/src/lib.rs index a6c9178b6..34b391a6d 100644 --- a/src/mission_control/src/lib.rs +++ b/src/mission_control/src/lib.rs @@ -23,8 +23,12 @@ use crate::guards::{ }; use crate::mgmt::canister::top_up_canister; use crate::mgmt::status::collect_statuses; -use crate::segments::orbiter::create_orbiter as create_orbiter_console; -use crate::segments::satellite::create_satellite as create_satellite_console; +use crate::segments::orbiter::{ + create_orbiter as create_orbiter_console, delete_orbiter as delete_orbiter_segment, +}; +use crate::segments::satellite::{ + create_satellite as create_satellite_console, delete_satellite as delete_satellite_segment, +}; use crate::segments::store::get_orbiters; use crate::store::{ get_user as get_user_store, @@ -162,6 +166,13 @@ async fn del_satellites_controllers(satellite_ids: Vec, controllers } } +#[update(guard = "caller_is_user_or_admin_controller")] +async fn delete_satellite(satellite_id: SatelliteId, cycles_to_retain: u128) { + delete_satellite_segment(&satellite_id, cycles_to_retain) + .await + .unwrap_or_else(|e| trap(&e)); +} + /// Orbiters #[query(guard = "caller_is_user_or_admin_controller")] @@ -203,6 +214,13 @@ async fn del_orbiters_controllers(orbiter_ids: Vec, controllers: Vec< } } +#[update(guard = "caller_is_user_or_admin_controller")] +async fn delete_orbiter(orbiter_id: OrbiterId, cycles_to_retain: u128) { + delete_orbiter_segment(&orbiter_id, cycles_to_retain) + .await + .unwrap_or_else(|e| trap(&e)); +} + /// Mgmt #[update(guard = "caller_is_user_or_admin_controller")] diff --git a/src/mission_control/src/mgmt/canister.rs b/src/mission_control/src/mgmt/canister.rs index 93f6028cd..ac2e90f39 100644 --- a/src/mission_control/src/mgmt/canister.rs +++ b/src/mission_control/src/mgmt/canister.rs @@ -1,5 +1,6 @@ use candid::Principal; use ic_cdk::api::call::CallResult; +use ic_cdk::api::management_canister::main::CanisterId; use ic_cdk::call; use ic_ledger_types::{Subaccount, Tokens}; use shared::constants::{IC_TRANSACTION_FEE_ICP, MEMO_CANISTER_TOP_UP}; @@ -7,7 +8,7 @@ use shared::env::CMC; use shared::ledger::transfer_payment; use shared::types::cmc::{Cycles, NotifyError, TopUpCanisterArgs}; -pub async fn top_up_canister(canister_id: &Principal, amount: &Tokens) -> Result<(), String> { +pub async fn top_up_canister(canister_id: &CanisterId, amount: &Tokens) -> Result<(), String> { // We need to hold back 1 transaction fee for the 'send' and also 1 for the 'notify' let send_amount = Tokens::from_e8s(amount.e8s() - (2 * IC_TRANSACTION_FEE_ICP.e8s())); diff --git a/src/mission_control/src/segments/canister.rs b/src/mission_control/src/segments/canister.rs index a03910c1d..9f5a1dca1 100644 --- a/src/mission_control/src/segments/canister.rs +++ b/src/mission_control/src/segments/canister.rs @@ -1,12 +1,13 @@ use crate::store::get_user; use candid::Principal; use ic_cdk::api::call::CallResult; -use ic_cdk::call; +use ic_cdk::{call, id}; use ic_ledger_types::{BlockIndex, Tokens}; use shared::constants::{IC_TRANSACTION_FEE_ICP, MEMO_CANISTER_CREATE}; use shared::env::CONSOLE; +use shared::ic::{delete_segment, stop_segment}; use shared::ledger::{transfer_payment, SUB_ACCOUNT}; -use shared::types::interface::GetCreateCanisterFeeArgs; +use shared::types::interface::{DepositCyclesArgs, GetCreateCanisterFeeArgs}; use shared::types::state::UserId; use std::future::Future; @@ -51,3 +52,25 @@ where } } } + +pub async fn delete_canister(segment_id: &Principal, cycles_to_retain: u128) -> Result<(), String> { + deposit_cycles(segment_id, cycles_to_retain).await?; + + stop_segment(*segment_id).await?; + + delete_segment(*segment_id).await +} + +async fn deposit_cycles(segment_id: &Principal, cycles_to_retain: u128) -> Result<(), String> { + let args = DepositCyclesArgs { + destination_id: id(), + cycles_to_retain, + }; + + let result: CallResult<((),)> = call(*segment_id, "deposit_cycles", (args,)).await; + + match result { + Err((_, message)) => Err(["Deposit cycles failed.", &message].join(" - ")), + Ok(_) => Ok(()), + } +} diff --git a/src/mission_control/src/segments/orbiter.rs b/src/mission_control/src/segments/orbiter.rs index bde77f237..d13239a24 100644 --- a/src/mission_control/src/segments/orbiter.rs +++ b/src/mission_control/src/segments/orbiter.rs @@ -1,5 +1,5 @@ -use crate::segments::canister::create_canister; -use crate::segments::store::add_orbiter; +use crate::segments::canister::{create_canister, delete_canister}; +use crate::segments::store::{add_orbiter, delete_orbiter as delete_orbiter_store, get_orbiter}; use crate::types::state::Orbiter; use candid::Principal; use ic_cdk::api::call::CallResult; @@ -13,6 +13,21 @@ pub async fn create_orbiter(name: &Option) -> Result { create_canister("get_create_orbiter_fee", create_and_save_orbiter, name).await } +pub async fn delete_orbiter(orbiter_id: &OrbiterId, cycles_to_retain: u128) -> Result<(), String> { + let orbiter = get_orbiter(orbiter_id); + + match orbiter { + None => Err("Orbiter not found or not owned by this mission control.".to_string()), + Some(_) => { + delete_canister(orbiter_id, cycles_to_retain).await?; + + delete_orbiter_store(orbiter_id); + + Ok(()) + } + } +} + async fn create_and_save_orbiter( user: UserId, name: Option, diff --git a/src/mission_control/src/segments/satellite.rs b/src/mission_control/src/segments/satellite.rs index be6c98dce..140ac03c5 100644 --- a/src/mission_control/src/segments/satellite.rs +++ b/src/mission_control/src/segments/satellite.rs @@ -1,5 +1,7 @@ -use crate::segments::canister::create_canister; -use crate::segments::store::add_satellite; +use crate::segments::canister::{create_canister, delete_canister}; +use crate::segments::store::{ + add_satellite, delete_satellite as delete_satellite_store, get_satellite, +}; use crate::types::state::Satellite; use candid::Principal; use ic_cdk::api::call::CallResult; @@ -18,6 +20,24 @@ pub async fn create_satellite(name: &str) -> Result { .await } +pub async fn delete_satellite( + satellite_id: &SatelliteId, + cycles_to_retain: u128, +) -> Result<(), String> { + let satellite = get_satellite(satellite_id); + + match satellite { + None => Err("Satellite not found or not owned by this mission control.".to_string()), + Some(_) => { + delete_canister(satellite_id, cycles_to_retain).await?; + + delete_satellite_store(satellite_id); + + Ok(()) + } + } +} + async fn create_and_save_satellite( user: UserId, name: Option, diff --git a/src/mission_control/src/segments/store.rs b/src/mission_control/src/segments/store.rs index 0d4a644c7..8885fc32e 100644 --- a/src/mission_control/src/segments/store.rs +++ b/src/mission_control/src/segments/store.rs @@ -11,6 +11,14 @@ pub fn get_satellites() -> Satellites { STATE.with(|state| state.borrow().stable.satellites.clone()) } +pub fn get_satellite(satellite_id: &SatelliteId) -> Option { + STATE.with(|state| get_segment_impl(satellite_id, &state.borrow().stable.satellites)) +} + +pub fn delete_satellite(satellite_id: &SatelliteId) -> Option { + STATE.with(|state| delete_segment_impl(satellite_id, &mut state.borrow_mut().stable.satellites)) +} + pub fn add_satellite(satellite_id: &SatelliteId, name: &Option) -> Satellite { STATE.with(|state| { add_segment_impl( @@ -40,7 +48,15 @@ pub fn get_orbiters() -> Orbiters { STATE.with(|state| state.borrow().stable.orbiters.clone()) } -pub fn add_orbiter(orbiter_id: &SatelliteId, name: &Option) -> Orbiter { +pub fn get_orbiter(orbiter_id: &OrbiterId) -> Option { + STATE.with(|state| get_segment_impl(orbiter_id, &state.borrow().stable.orbiters)) +} + +pub fn delete_orbiter(orbiter_id: &OrbiterId) -> Option { + STATE.with(|state| delete_segment_impl(orbiter_id, &mut state.borrow_mut().stable.orbiters)) +} + +pub fn add_orbiter(orbiter_id: &OrbiterId, name: &Option) -> Orbiter { STATE.with(|state| { add_segment_impl( orbiter_id, @@ -75,6 +91,17 @@ fn add_segment_impl( value.clone() } +fn delete_segment_impl( + id: &K, + state: &mut HashMap, +) -> Option { + state.remove(id) +} + +fn get_segment_impl(id: &K, state: &HashMap) -> Option { + state.get(id).cloned() +} + fn set_metadata_impl>( id: &K, metadata: &Metadata, diff --git a/src/observatory/src/lib.rs b/src/observatory/src/lib.rs index 56526b60a..65e0b05a6 100644 --- a/src/observatory/src/lib.rs +++ b/src/observatory/src/lib.rs @@ -12,9 +12,8 @@ use crate::cron_jobs::cron_jobs; use crate::guards::{caller_can_execute_cron_jobs, caller_is_admin_controller}; use crate::reports::collect_statuses as collect_statuses_report; use crate::store::{ - delete_controllers, get_cron_tab as get_cron_tab_store, + delete_controllers, get_cron_tab as get_cron_tab_store, get_statuses as get_statuses_store, set_controllers as set_controllers_store, set_cron_tab as set_cron_tab_store, - get_statuses as get_statuses_store }; use crate::types::interface::{ListStatuses, ListStatusesArgs, SetCronTab}; use crate::types::state::{Archive, ArchiveStatuses, CronTab, StableState, State}; diff --git a/src/observatory/src/store.rs b/src/observatory/src/store.rs index b0ec349ea..d7f57c0e6 100644 --- a/src/observatory/src/store.rs +++ b/src/observatory/src/store.rs @@ -129,4 +129,4 @@ pub fn get_statuses(user: &UserId) -> Option { fn get_statuses_impl(user: &UserId, state: &StableState) -> Option { let statuses = state.archive.statuses.get(user); statuses.cloned() -} \ No newline at end of file +} diff --git a/src/orbiter/src/lib.rs b/src/orbiter/src/lib.rs index 80ef22db1..3c5cebfb2 100644 --- a/src/orbiter/src/lib.rs +++ b/src/orbiter/src/lib.rs @@ -44,7 +44,10 @@ use shared::constants::MAX_NUMBER_OF_SATELLITE_CONTROLLERS; use shared::controllers::{ assert_max_number_of_controllers, assert_no_anonymous_controller, init_controllers, }; -use shared::types::interface::{DeleteControllersArgs, SegmentArgs, SetControllersArgs}; +use shared::ic::deposit_cycles as deposit_cycles_shared; +use shared::types::interface::{ + DeleteControllersArgs, DepositCyclesArgs, SegmentArgs, SetControllersArgs, +}; use shared::types::state::{ControllerScope, Controllers, SatelliteId}; use std::mem; @@ -267,6 +270,13 @@ fn list_satellite_configs() -> SatelliteConfigs { /// Mgmt +#[update(guard = "caller_is_admin_controller")] +async fn deposit_cycles(args: DepositCyclesArgs) { + deposit_cycles_shared(args) + .await + .unwrap_or_else(|e| trap(&e)) +} + #[query] fn version() -> String { env!("CARGO_PKG_VERSION").to_string() diff --git a/src/satellite/src/lib.rs b/src/satellite/src/lib.rs index ef7dc8605..dda9c1414 100644 --- a/src/satellite/src/lib.rs +++ b/src/satellite/src/lib.rs @@ -61,7 +61,10 @@ use shared::constants::MAX_NUMBER_OF_SATELLITE_CONTROLLERS; use shared::controllers::{ assert_max_number_of_controllers, assert_no_anonymous_controller, init_controllers, }; -use shared::types::interface::{DeleteControllersArgs, SegmentArgs, SetControllersArgs}; +use shared::ic::deposit_cycles as deposit_cycles_shared; +use shared::types::interface::{ + DeleteControllersArgs, DepositCyclesArgs, SegmentArgs, SetControllersArgs, +}; use shared::types::state::{ControllerScope, Controllers}; use std::mem; use storage::http::types::{ @@ -454,6 +457,13 @@ fn del_assets(collection: CollectionKey) { /// Mgmt +#[update(guard = "caller_is_admin_controller")] +async fn deposit_cycles(args: DepositCyclesArgs) { + deposit_cycles_shared(args) + .await + .unwrap_or_else(|e| trap(&e)) +} + #[query] fn version() -> String { env!("CARGO_PKG_VERSION").to_string() diff --git a/src/shared/src/ic.rs b/src/shared/src/ic.rs index a8023271b..51091ed2d 100644 --- a/src/shared/src/ic.rs +++ b/src/shared/src/ic.rs @@ -1,14 +1,16 @@ use crate::constants::CREATE_CANISTER_CYCLES; use crate::types::ic::WasmArg; +use crate::types::interface::DepositCyclesArgs; use crate::types::state::{SegmentStatus, SegmentStatusResult}; use candid::Principal; use ic_cdk::api::call::CallResult; use ic_cdk::api::management_canister::main::{ - canister_status as ic_canister_status, create_canister, install_code as ic_install_code, + canister_status as ic_canister_status, create_canister, delete_canister, + deposit_cycles as ic_deposit_cycles, install_code as ic_install_code, stop_canister, update_settings, CanisterId, CanisterIdRecord, CanisterInstallMode, CanisterSettings, CreateCanisterArgument, InstallCodeArgument, UpdateSettingsArgument, }; -use ic_cdk::api::time; +use ic_cdk::api::{canister_balance128, time}; pub async fn create_canister_install_code( controllers: Vec, @@ -88,3 +90,52 @@ pub async fn segment_status(canister_id: CanisterId) -> SegmentStatusResult { Err((_, message)) => Err(["Failed to get canister status: ".to_string(), message].join("")), } } + +pub async fn deposit_cycles( + DepositCyclesArgs { + destination_id, + cycles_to_retain, + }: DepositCyclesArgs, +) -> Result<(), String> { + let balance = canister_balance128(); + + if balance < cycles_to_retain { + return Err(format!( + "Balance ({}) is lower than the amount of cycles {} to retain.", + balance, cycles_to_retain + )); + } + + let cycles = balance - cycles_to_retain; + + let result = ic_deposit_cycles( + CanisterIdRecord { + canister_id: destination_id, + }, + cycles, + ) + .await; + + match result { + Err((_, message)) => Err(["Deposit cycles failed.", &message].join(" - ")), + Ok(_) => Ok(()), + } +} + +pub async fn stop_segment(canister_id: CanisterId) -> Result<(), String> { + let result = stop_canister(CanisterIdRecord { canister_id }).await; + + match result { + Err((_, message)) => Err(["Cannot stop segment.", &message].join(" - ")), + Ok(_) => Ok(()), + } +} + +pub async fn delete_segment(canister_id: CanisterId) -> Result<(), String> { + let result = delete_canister(CanisterIdRecord { canister_id }).await; + + match result { + Err((_, message)) => Err(["Cannot delete segment.", &message].join(" - ")), + Ok(_) => Ok(()), + } +} diff --git a/src/shared/src/types.rs b/src/shared/src/types.rs index 8a566bc0f..5fb98400c 100644 --- a/src/shared/src/types.rs +++ b/src/shared/src/types.rs @@ -53,7 +53,7 @@ pub mod state { pub mod interface { use crate::types::cronjob::CronJobStatusesSegments; use crate::types::state::{ControllerId, ControllerScope, Metadata, MissionControlId, UserId}; - use candid::CandidType; + use candid::{CandidType, Principal}; use ic_ledger_types::BlockIndex; use serde::Deserialize; @@ -114,6 +114,12 @@ pub mod interface { pub satellites: CronJobStatusesSegments, pub orbiters: CronJobStatusesSegments, } + + #[derive(CandidType, Deserialize)] + pub struct DepositCyclesArgs { + pub destination_id: Principal, + pub cycles_to_retain: u128, + } } pub mod ledger { From fcca354b08754de46efd6215c33318b004e2f0c0 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 17 Nov 2023 11:44:13 +0100 Subject: [PATCH 2/6] feat: did types Signed-off-by: David Dal Busco --- src/declarations/mission_control/mission_control.did.d.ts | 2 ++ .../mission_control/mission_control.factory.did.js | 2 ++ src/declarations/orbiter/orbiter.did.d.ts | 5 +++++ src/declarations/orbiter/orbiter.factory.did.js | 5 +++++ src/declarations/satellite/satellite.did.d.ts | 5 +++++ src/declarations/satellite/satellite.factory.did.js | 5 +++++ src/declarations/satellite/satellite.factory.did.mjs | 5 +++++ src/mission_control/mission_control.did | 2 ++ src/orbiter/orbiter.did | 5 +++++ src/satellite/satellite.did | 5 +++++ 10 files changed, 41 insertions(+) diff --git a/src/declarations/mission_control/mission_control.did.d.ts b/src/declarations/mission_control/mission_control.did.d.ts index 996711cff..31bb9cc03 100644 --- a/src/declarations/mission_control/mission_control.did.d.ts +++ b/src/declarations/mission_control/mission_control.did.d.ts @@ -74,6 +74,8 @@ export interface _SERVICE { del_mission_control_controllers: ActorMethod<[Array], undefined>; del_orbiters_controllers: ActorMethod<[Array, Array], undefined>; del_satellites_controllers: ActorMethod<[Array, Array], undefined>; + delete_orbiter: ActorMethod<[Principal, bigint], undefined>; + delete_satellite: ActorMethod<[Principal, bigint], undefined>; get_user: ActorMethod<[], Principal>; list_mission_control_controllers: ActorMethod<[], Array<[Principal, Controller]>>; list_mission_control_statuses: ActorMethod<[], Array<[bigint, Result]>>; diff --git a/src/declarations/mission_control/mission_control.factory.did.js b/src/declarations/mission_control/mission_control.factory.did.js index 8d7be02a8..49a50fe48 100644 --- a/src/declarations/mission_control/mission_control.factory.did.js +++ b/src/declarations/mission_control/mission_control.factory.did.js @@ -78,6 +78,8 @@ export const idlFactory = ({ IDL }) => { del_mission_control_controllers: IDL.Func([IDL.Vec(IDL.Principal)], [], []), del_orbiters_controllers: IDL.Func([IDL.Vec(IDL.Principal), IDL.Vec(IDL.Principal)], [], []), del_satellites_controllers: IDL.Func([IDL.Vec(IDL.Principal), IDL.Vec(IDL.Principal)], [], []), + delete_orbiter: IDL.Func([IDL.Principal, IDL.Nat], [], []), + delete_satellite: IDL.Func([IDL.Principal, IDL.Nat], [], []), get_user: IDL.Func([], [IDL.Principal], ['query']), list_mission_control_controllers: IDL.Func( [], diff --git a/src/declarations/orbiter/orbiter.did.d.ts b/src/declarations/orbiter/orbiter.did.d.ts index e37f6d561..0e1e6f25b 100644 --- a/src/declarations/orbiter/orbiter.did.d.ts +++ b/src/declarations/orbiter/orbiter.did.d.ts @@ -19,6 +19,10 @@ export interface DelSatelliteConfig { export interface DeleteControllersArgs { controllers: Array; } +export interface DepositCyclesArgs { + cycles_to_retain: bigint; + destination_id: Principal; +} export interface GetAnalytics { to: [] | [bigint]; from: [] | [bigint]; @@ -91,6 +95,7 @@ export interface TrackEvent { export interface _SERVICE { del_controllers: ActorMethod<[DeleteControllersArgs], Array<[Principal, Controller]>>; del_satellite_config: ActorMethod<[Principal, DelSatelliteConfig], undefined>; + deposit_cycles: ActorMethod<[DepositCyclesArgs], undefined>; get_page_views: ActorMethod<[GetAnalytics], Array<[AnalyticKey, PageView]>>; get_track_events: ActorMethod<[GetAnalytics], Array<[AnalyticKey, TrackEvent]>>; list_controllers: ActorMethod<[], Array<[Principal, Controller]>>; diff --git a/src/declarations/orbiter/orbiter.factory.did.js b/src/declarations/orbiter/orbiter.factory.did.js index 72c15bbbd..7803a92ff 100644 --- a/src/declarations/orbiter/orbiter.factory.did.js +++ b/src/declarations/orbiter/orbiter.factory.did.js @@ -15,6 +15,10 @@ export const idlFactory = ({ IDL }) => { expires_at: IDL.Opt(IDL.Nat64) }); const DelSatelliteConfig = IDL.Record({ updated_at: IDL.Opt(IDL.Nat64) }); + const DepositCyclesArgs = IDL.Record({ + cycles_to_retain: IDL.Nat, + destination_id: IDL.Principal + }); const GetAnalytics = IDL.Record({ to: IDL.Opt(IDL.Nat64), from: IDL.Opt(IDL.Nat64), @@ -98,6 +102,7 @@ export const idlFactory = ({ IDL }) => { [] ), del_satellite_config: IDL.Func([IDL.Principal, DelSatelliteConfig], [], []), + deposit_cycles: IDL.Func([DepositCyclesArgs], [], []), get_page_views: IDL.Func( [GetAnalytics], [IDL.Vec(IDL.Tuple(AnalyticKey, PageView))], diff --git a/src/declarations/satellite/satellite.did.d.ts b/src/declarations/satellite/satellite.did.d.ts index 5b6aba629..dd2dab497 100644 --- a/src/declarations/satellite/satellite.did.d.ts +++ b/src/declarations/satellite/satellite.did.d.ts @@ -48,6 +48,10 @@ export interface DelDoc { export interface DeleteControllersArgs { controllers: Array; } +export interface DepositCyclesArgs { + cycles_to_retain: bigint; + destination_id: Principal; +} export interface Doc { updated_at: bigint; owner: Principal; @@ -194,6 +198,7 @@ export interface _SERVICE { del_custom_domain: ActorMethod<[string], undefined>; del_doc: ActorMethod<[string, string, DelDoc], undefined>; del_rule: ActorMethod<[RulesType, string, DelDoc], undefined>; + deposit_cycles: ActorMethod<[DepositCyclesArgs], undefined>; get_config: ActorMethod<[], Config>; get_doc: ActorMethod<[string, string], [] | [Doc]>; http_request: ActorMethod<[HttpRequest], HttpResponse>; diff --git a/src/declarations/satellite/satellite.factory.did.js b/src/declarations/satellite/satellite.factory.did.js index c74c5dfae..09dc7d0ad 100644 --- a/src/declarations/satellite/satellite.factory.did.js +++ b/src/declarations/satellite/satellite.factory.did.js @@ -21,6 +21,10 @@ export const idlFactory = ({ IDL }) => { }); const DelDoc = IDL.Record({ updated_at: IDL.Opt(IDL.Nat64) }); const RulesType = IDL.Variant({ Db: IDL.Null, Storage: IDL.Null }); + const DepositCyclesArgs = IDL.Record({ + cycles_to_retain: IDL.Nat, + destination_id: IDL.Principal + }); const StorageConfigRedirect = IDL.Record({ status_code: IDL.Nat16, location: IDL.Text @@ -194,6 +198,7 @@ export const idlFactory = ({ IDL }) => { del_custom_domain: IDL.Func([IDL.Text], [], []), del_doc: IDL.Func([IDL.Text, IDL.Text, DelDoc], [], []), del_rule: IDL.Func([RulesType, IDL.Text, DelDoc], [], []), + deposit_cycles: IDL.Func([DepositCyclesArgs], [], []), get_config: IDL.Func([], [Config], []), get_doc: IDL.Func([IDL.Text, IDL.Text], [IDL.Opt(Doc)], ['query']), http_request: IDL.Func([HttpRequest], [HttpResponse], ['query']), diff --git a/src/declarations/satellite/satellite.factory.did.mjs b/src/declarations/satellite/satellite.factory.did.mjs index c74c5dfae..09dc7d0ad 100644 --- a/src/declarations/satellite/satellite.factory.did.mjs +++ b/src/declarations/satellite/satellite.factory.did.mjs @@ -21,6 +21,10 @@ export const idlFactory = ({ IDL }) => { }); const DelDoc = IDL.Record({ updated_at: IDL.Opt(IDL.Nat64) }); const RulesType = IDL.Variant({ Db: IDL.Null, Storage: IDL.Null }); + const DepositCyclesArgs = IDL.Record({ + cycles_to_retain: IDL.Nat, + destination_id: IDL.Principal + }); const StorageConfigRedirect = IDL.Record({ status_code: IDL.Nat16, location: IDL.Text @@ -194,6 +198,7 @@ export const idlFactory = ({ IDL }) => { del_custom_domain: IDL.Func([IDL.Text], [], []), del_doc: IDL.Func([IDL.Text, IDL.Text, DelDoc], [], []), del_rule: IDL.Func([RulesType, IDL.Text, DelDoc], [], []), + deposit_cycles: IDL.Func([DepositCyclesArgs], [], []), get_config: IDL.Func([], [Config], []), get_doc: IDL.Func([IDL.Text, IDL.Text], [IDL.Opt(Doc)], ['query']), http_request: IDL.Func([HttpRequest], [HttpResponse], ['query']), diff --git a/src/mission_control/mission_control.did b/src/mission_control/mission_control.did index 5e4ee2aa6..da8e4eca9 100644 --- a/src/mission_control/mission_control.did +++ b/src/mission_control/mission_control.did @@ -69,6 +69,8 @@ service : () -> { del_mission_control_controllers : (vec principal) -> (); del_orbiters_controllers : (vec principal, vec principal) -> (); del_satellites_controllers : (vec principal, vec principal) -> (); + delete_orbiter : (principal, nat) -> (); + delete_satellite : (principal, nat) -> (); get_user : () -> (principal) query; list_mission_control_controllers : () -> ( vec record { principal; Controller }, diff --git a/src/orbiter/orbiter.did b/src/orbiter/orbiter.did index 9c3d97c20..0eb6f24cb 100644 --- a/src/orbiter/orbiter.did +++ b/src/orbiter/orbiter.did @@ -9,6 +9,10 @@ type Controller = record { type ControllerScope = variant { Write; Admin }; type DelSatelliteConfig = record { updated_at : opt nat64 }; type DeleteControllersArgs = record { controllers : vec principal }; +type DepositCyclesArgs = record { + cycles_to_retain : nat; + destination_id : principal; +}; type GetAnalytics = record { to : opt nat64; from : opt nat64; @@ -77,6 +81,7 @@ service : () -> { vec record { principal; Controller }, ); del_satellite_config : (principal, DelSatelliteConfig) -> (); + deposit_cycles : (DepositCyclesArgs) -> (); get_page_views : (GetAnalytics) -> ( vec record { AnalyticKey; PageView }, ) query; diff --git a/src/satellite/satellite.did b/src/satellite/satellite.did index 7440b997a..ee6fd0218 100644 --- a/src/satellite/satellite.did +++ b/src/satellite/satellite.did @@ -39,6 +39,10 @@ type CustomDomain = record { }; type DelDoc = record { updated_at : opt nat64 }; type DeleteControllersArgs = record { controllers : vec principal }; +type DepositCyclesArgs = record { + cycles_to_retain : nat; + destination_id : principal; +}; type Doc = record { updated_at : nat64; owner : principal; @@ -167,6 +171,7 @@ service : () -> { del_custom_domain : (text) -> (); del_doc : (text, text, DelDoc) -> (); del_rule : (RulesType, text, DelDoc) -> (); + deposit_cycles : (DepositCyclesArgs) -> (); get_config : () -> (Config); get_doc : (text, text) -> (opt Doc) query; http_request : (HttpRequest) -> (HttpResponse) query; From 280bd599e8d25c6017520923beafb07576a3f4e5 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 17 Nov 2023 11:45:57 +0100 Subject: [PATCH 3/6] feat: for the best and worth, use del_ instead of delete_ Signed-off-by: David Dal Busco --- .../mission_control/mission_control.did.d.ts | 4 ++-- .../mission_control.factory.did.js | 4 ++-- src/mission_control/mission_control.did | 4 ++-- src/mission_control/src/lib.rs | 16 ++++++---------- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/declarations/mission_control/mission_control.did.d.ts b/src/declarations/mission_control/mission_control.did.d.ts index 31bb9cc03..4d187e93a 100644 --- a/src/declarations/mission_control/mission_control.did.d.ts +++ b/src/declarations/mission_control/mission_control.did.d.ts @@ -72,10 +72,10 @@ export interface _SERVICE { create_orbiter: ActorMethod<[[] | [string]], Orbiter>; create_satellite: ActorMethod<[string], Satellite>; del_mission_control_controllers: ActorMethod<[Array], undefined>; + del_orbiter: ActorMethod<[Principal, bigint], undefined>; del_orbiters_controllers: ActorMethod<[Array, Array], undefined>; + del_satellite: ActorMethod<[Principal, bigint], undefined>; del_satellites_controllers: ActorMethod<[Array, Array], undefined>; - delete_orbiter: ActorMethod<[Principal, bigint], undefined>; - delete_satellite: ActorMethod<[Principal, bigint], undefined>; get_user: ActorMethod<[], Principal>; list_mission_control_controllers: ActorMethod<[], Array<[Principal, Controller]>>; list_mission_control_statuses: ActorMethod<[], Array<[bigint, Result]>>; diff --git a/src/declarations/mission_control/mission_control.factory.did.js b/src/declarations/mission_control/mission_control.factory.did.js index 49a50fe48..186967c38 100644 --- a/src/declarations/mission_control/mission_control.factory.did.js +++ b/src/declarations/mission_control/mission_control.factory.did.js @@ -76,10 +76,10 @@ export const idlFactory = ({ IDL }) => { create_orbiter: IDL.Func([IDL.Opt(IDL.Text)], [Orbiter], []), create_satellite: IDL.Func([IDL.Text], [Satellite], []), del_mission_control_controllers: IDL.Func([IDL.Vec(IDL.Principal)], [], []), + del_orbiter: IDL.Func([IDL.Principal, IDL.Nat], [], []), del_orbiters_controllers: IDL.Func([IDL.Vec(IDL.Principal), IDL.Vec(IDL.Principal)], [], []), + del_satellite: IDL.Func([IDL.Principal, IDL.Nat], [], []), del_satellites_controllers: IDL.Func([IDL.Vec(IDL.Principal), IDL.Vec(IDL.Principal)], [], []), - delete_orbiter: IDL.Func([IDL.Principal, IDL.Nat], [], []), - delete_satellite: IDL.Func([IDL.Principal, IDL.Nat], [], []), get_user: IDL.Func([], [IDL.Principal], ['query']), list_mission_control_controllers: IDL.Func( [], diff --git a/src/mission_control/mission_control.did b/src/mission_control/mission_control.did index da8e4eca9..cc6f49cd0 100644 --- a/src/mission_control/mission_control.did +++ b/src/mission_control/mission_control.did @@ -67,10 +67,10 @@ service : () -> { create_orbiter : (opt text) -> (Orbiter); create_satellite : (text) -> (Satellite); del_mission_control_controllers : (vec principal) -> (); + del_orbiter : (principal, nat) -> (); del_orbiters_controllers : (vec principal, vec principal) -> (); + del_satellite : (principal, nat) -> (); del_satellites_controllers : (vec principal, vec principal) -> (); - delete_orbiter : (principal, nat) -> (); - delete_satellite : (principal, nat) -> (); get_user : () -> (principal) query; list_mission_control_controllers : () -> ( vec record { principal; Controller }, diff --git a/src/mission_control/src/lib.rs b/src/mission_control/src/lib.rs index 34b391a6d..c5757f732 100644 --- a/src/mission_control/src/lib.rs +++ b/src/mission_control/src/lib.rs @@ -23,12 +23,8 @@ use crate::guards::{ }; use crate::mgmt::canister::top_up_canister; use crate::mgmt::status::collect_statuses; -use crate::segments::orbiter::{ - create_orbiter as create_orbiter_console, delete_orbiter as delete_orbiter_segment, -}; -use crate::segments::satellite::{ - create_satellite as create_satellite_console, delete_satellite as delete_satellite_segment, -}; +use crate::segments::orbiter::{create_orbiter as create_orbiter_console, delete_orbiter}; +use crate::segments::satellite::{create_satellite as create_satellite_console, delete_satellite}; use crate::segments::store::get_orbiters; use crate::store::{ get_user as get_user_store, @@ -167,8 +163,8 @@ async fn del_satellites_controllers(satellite_ids: Vec, controllers } #[update(guard = "caller_is_user_or_admin_controller")] -async fn delete_satellite(satellite_id: SatelliteId, cycles_to_retain: u128) { - delete_satellite_segment(&satellite_id, cycles_to_retain) +async fn del_satellite(satellite_id: SatelliteId, cycles_to_retain: u128) { + delete_satellite(&satellite_id, cycles_to_retain) .await .unwrap_or_else(|e| trap(&e)); } @@ -215,8 +211,8 @@ async fn del_orbiters_controllers(orbiter_ids: Vec, controllers: Vec< } #[update(guard = "caller_is_user_or_admin_controller")] -async fn delete_orbiter(orbiter_id: OrbiterId, cycles_to_retain: u128) { - delete_orbiter_segment(&orbiter_id, cycles_to_retain) +async fn del_orbiter(orbiter_id: OrbiterId, cycles_to_retain: u128) { + delete_orbiter(&orbiter_id, cycles_to_retain) .await .unwrap_or_else(|e| trap(&e)); } From 07fbd78097cca54f87901619b0e5a3c874e4bf19 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 17 Nov 2023 14:12:16 +0100 Subject: [PATCH 4/6] feat: delete satellite integrated to UI Signed-off-by: David Dal Busco --- .../src/lib/api/mission-control.api.ts | 26 +++ .../modals/CanisterDeleteModal.svelte | 192 ++++++++++++++++++ .../src/lib/components/modals/Modals.svelte | 5 + .../modals/SatelliteDeleteModal.svelte | 30 +++ .../satellites/SatelliteDelete.svelte | 35 ++++ .../satellites/SatelliteStopStart.svelte | 8 +- .../satellites/SatelliteTopUp.svelte | 7 +- src/frontend/src/lib/i18n/en.json | 10 +- src/frontend/src/lib/i18n/it.json | 10 +- src/frontend/src/lib/i18n/zh-cn.json | 10 +- src/frontend/src/lib/types/i18n.d.ts | 8 + src/frontend/src/lib/types/modal.ts | 11 +- src/frontend/src/lib/utils/cycles.utils.ts | 3 +- 13 files changed, 343 insertions(+), 12 deletions(-) create mode 100644 src/frontend/src/lib/components/modals/CanisterDeleteModal.svelte create mode 100644 src/frontend/src/lib/components/modals/SatelliteDeleteModal.svelte create mode 100644 src/frontend/src/lib/components/satellites/SatelliteDelete.svelte diff --git a/src/frontend/src/lib/api/mission-control.api.ts b/src/frontend/src/lib/api/mission-control.api.ts index 5ce524b64..10b39dda4 100644 --- a/src/frontend/src/lib/api/mission-control.api.ts +++ b/src/frontend/src/lib/api/mission-control.api.ts @@ -228,3 +228,29 @@ export const deleteOrbitersController = async ({ const actor = await getMissionControlActor(missionControlId); await actor.del_orbiters_controllers(orbiterIds, [controller]); }; + +export const deleteSatellite = async ({ + missionControlId, + satelliteId, + cycles_to_retain +}: { + missionControlId: Principal; + satelliteId: Principal; + cycles_to_retain: bigint; +}) => { + const { del_satellite } = await getMissionControlActor(missionControlId); + await del_satellite(satelliteId, cycles_to_retain); +}; + +export const deleteOrbiter = async ({ + missionControlId, + orbiterId, + cycles_to_retain +}: { + missionControlId: Principal; + orbiterId: Principal; + cycles_to_retain: bigint; +}) => { + const { del_orbiter } = await getMissionControlActor(missionControlId); + await del_orbiter(orbiterId, cycles_to_retain); +}; diff --git a/src/frontend/src/lib/components/modals/CanisterDeleteModal.svelte b/src/frontend/src/lib/components/modals/CanisterDeleteModal.svelte new file mode 100644 index 000000000..895097840 --- /dev/null +++ b/src/frontend/src/lib/components/modals/CanisterDeleteModal.svelte @@ -0,0 +1,192 @@ + + + + {#if steps === 'in_progress'} + +

{$i18n.canisters.delete_in_progress}

+
+ {:else} +
+

+ {@html i18nFormat($i18n.canisters.delete_title, [ + { + placeholder: '{0}', + value: segment.replace('_', ' ') + } + ])} +

+ +

+ {@html i18nFormat($i18n.canisters.delete_explanation, [ + { + placeholder: '{0}', + value: segment.replace('_', ' ') + }, + { + placeholder: '{1}', + value: segment.replace('_', ' ') + } + ])} +

+ +

+ {@html i18nFormat($i18n.canisters.delete_customization, [ + { + placeholder: '{0}', + value: segment.replace('_', ' ') + }, + { + placeholder: '{1}', + value: formatTCycles(currentCycles) + } + ])} +

+ + + {$i18n.canisters.cycles_to_retain} + + + + +

+ {@html i18nFormat($i18n.canisters.cycles_to_transfer, [ + { + placeholder: '{0}', + value: formatTCycles(depositCycles) + } + ])} +

+ +

+ + {@html i18nFormat($i18n.canisters.delete_info, [ + { + placeholder: '{0}', + value: segment.replace('_', ' ') + } + ])} +

+ + +
+ {/if} +
+ + diff --git a/src/frontend/src/lib/components/modals/Modals.svelte b/src/frontend/src/lib/components/modals/Modals.svelte index 498628b00..6511cb855 100644 --- a/src/frontend/src/lib/components/modals/Modals.svelte +++ b/src/frontend/src/lib/components/modals/Modals.svelte @@ -11,6 +11,7 @@ import OrbiterCreateModal from '$lib/components/modals/OrbiterCreateModal.svelte'; import OrbiterUpgradeModal from '$lib/components/modals/OrbiterUpgradeModal.svelte'; import OrbiterTopUpModal from '$lib/components/modals/OrbiterTopUpModal.svelte'; + import SatelliteDeleteModal from '$lib/components/modals/SatelliteDeleteModal.svelte'; let modal: JunoModal | undefined = undefined; @@ -58,3 +59,7 @@ {#if modal?.type === 'upgrade_orbiter' && nonNullish(modal.detail)} {/if} + +{#if modal?.type === 'delete_satellite' && nonNullish(modal.detail)} + +{/if} diff --git a/src/frontend/src/lib/components/modals/SatelliteDeleteModal.svelte b/src/frontend/src/lib/components/modals/SatelliteDeleteModal.svelte new file mode 100644 index 000000000..0f9c49b39 --- /dev/null +++ b/src/frontend/src/lib/components/modals/SatelliteDeleteModal.svelte @@ -0,0 +1,30 @@ + + + diff --git a/src/frontend/src/lib/components/satellites/SatelliteDelete.svelte b/src/frontend/src/lib/components/satellites/SatelliteDelete.svelte new file mode 100644 index 000000000..119be1ce5 --- /dev/null +++ b/src/frontend/src/lib/components/satellites/SatelliteDelete.svelte @@ -0,0 +1,35 @@ + + + onSyncCanister(canister)} /> + + diff --git a/src/frontend/src/lib/components/satellites/SatelliteStopStart.svelte b/src/frontend/src/lib/components/satellites/SatelliteStopStart.svelte index c339a3d91..2fba112d6 100644 --- a/src/frontend/src/lib/components/satellites/SatelliteStopStart.svelte +++ b/src/frontend/src/lib/components/satellites/SatelliteStopStart.svelte @@ -1,7 +1,7 @@