Skip to content

Commit

Permalink
feat(station): prune external canister request (#437)
Browse files Browse the repository at this point in the history
This PR adds a new request type to prune a resource (a particular
snapshot, the entire chunk store, or the entire state - heap and stable
memory) of an external canister.
  • Loading branch information
mraszyk authored Nov 26, 2024
1 parent 830dca6 commit 65cba91
Show file tree
Hide file tree
Showing 21 changed files with 521 additions and 12 deletions.
23 changes: 23 additions & 0 deletions apps/wallet/src/generated/station/station.did
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,21 @@ type RestoreExternalCanisterOperation = record {
input : RestoreExternalCanisterOperationInput;
};

type PruneExternalCanisterOperationInput = record {
// The canister to prune.
canister_id : principal;
// The resource to prune.
prune : variant {
chunk_store;
snapshot : text;
state;
};
};

type PruneExternalCanisterOperation = record {
input : PruneExternalCanisterOperationInput;
};

type EditPermissionOperationInput = record {
// The updated resource that this policy will apply to.
resource : Resource;
Expand Down Expand Up @@ -942,6 +957,8 @@ type RequestOperation = variant {
SnapshotExternalCanister : SnapshotExternalCanisterOperation;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister : RestoreExternalCanisterOperation;
// An operation for pruning an external canister.
PruneExternalCanister : PruneExternalCanisterOperation;
// An operation for editing an permission.
EditPermission : EditPermissionOperation;
// An operation for adding a request policy.
Expand Down Expand Up @@ -995,6 +1012,8 @@ type RequestOperationInput = variant {
SnapshotExternalCanister : SnapshotExternalCanisterOperationInput;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister : RestoreExternalCanisterOperationInput;
// An operation for pruning an external canister.
PruneExternalCanister : PruneExternalCanisterOperationInput;
// An operation for editing an permission.
EditPermission : EditPermissionOperationInput;
// An operation for adding a request policy.
Expand Down Expand Up @@ -1048,6 +1067,8 @@ type RequestOperationType = variant {
SnapshotExternalCanister;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister;
// An operation for pruning an external canister.
PruneExternalCanister;
// An operation for editing an permission.
EditPermission;
// An operation for adding a request policy.
Expand Down Expand Up @@ -1200,6 +1221,8 @@ type ListRequestsOperationType = variant {
SnapshotExternalCanister : opt principal;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister : opt principal;
// An operation for pruning an external canister.
PruneExternalCanister : opt principal;
// An operation for editing an permission.
EditPermission;
// An operation for adding a request policy.
Expand Down
13 changes: 13 additions & 0 deletions apps/wallet/src/generated/station/station.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ export interface ListRequestsInput {
export type ListRequestsOperationType = { 'AddUserGroup' : null } |
{ 'EditPermission' : null } |
{ 'SnapshotExternalCanister' : [] | [Principal] } |
{ 'PruneExternalCanister' : [] | [Principal] } |
{ 'ConfigureExternalCanister' : [] | [Principal] } |
{ 'ChangeExternalCanister' : [] | [Principal] } |
{ 'AddUser' : null } |
Expand Down Expand Up @@ -895,6 +896,15 @@ export interface PermissionCallerPrivileges {
}
export type PermissionResourceAction = { 'Read' : null } |
{ 'Update' : null };
export interface PruneExternalCanisterOperation {
'input' : PruneExternalCanisterOperationInput,
}
export interface PruneExternalCanisterOperationInput {
'canister_id' : Principal,
'prune' : { 'snapshot' : string } |
{ 'state' : null } |
{ 'chunk_store' : null },
}
export interface Quorum { 'min_approved' : number, 'approvers' : UserSpecifier }
export interface QuorumPercentage {
'min_approved' : number,
Expand Down Expand Up @@ -955,6 +965,7 @@ export type RequestExecutionSchedule = { 'Immediate' : null } |
export type RequestOperation = { 'AddUserGroup' : AddUserGroupOperation } |
{ 'EditPermission' : EditPermissionOperation } |
{ 'SnapshotExternalCanister' : SnapshotExternalCanisterOperation } |
{ 'PruneExternalCanister' : PruneExternalCanisterOperation } |
{ 'ConfigureExternalCanister' : ConfigureExternalCanisterOperation } |
{ 'ChangeExternalCanister' : ChangeExternalCanisterOperation } |
{ 'AddUser' : AddUserOperation } |
Expand Down Expand Up @@ -982,6 +993,7 @@ export type RequestOperationInput = {
} |
{ 'EditPermission' : EditPermissionOperationInput } |
{ 'SnapshotExternalCanister' : SnapshotExternalCanisterOperationInput } |
{ 'PruneExternalCanister' : PruneExternalCanisterOperationInput } |
{ 'ConfigureExternalCanister' : ConfigureExternalCanisterOperationInput } |
{ 'ChangeExternalCanister' : ChangeExternalCanisterOperationInput } |
{ 'AddUser' : AddUserOperationInput } |
Expand All @@ -1007,6 +1019,7 @@ export type RequestOperationInput = {
export type RequestOperationType = { 'AddUserGroup' : null } |
{ 'EditPermission' : null } |
{ 'SnapshotExternalCanister' : null } |
{ 'PruneExternalCanister' : null } |
{ 'ConfigureExternalCanister' : null } |
{ 'ChangeExternalCanister' : null } |
{ 'AddUser' : null } |
Expand Down
15 changes: 15 additions & 0 deletions apps/wallet/src/generated/station/station.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,17 @@ export const idlFactory = ({ IDL }) => {
'input' : SnapshotExternalCanisterOperationInput,
'snapshot_id' : IDL.Opt(IDL.Text),
});
const PruneExternalCanisterOperationInput = IDL.Record({
'canister_id' : IDL.Principal,
'prune' : IDL.Variant({
'snapshot' : IDL.Text,
'state' : IDL.Null,
'chunk_store' : IDL.Null,
}),
});
const PruneExternalCanisterOperation = IDL.Record({
'input' : PruneExternalCanisterOperationInput,
});
const Allow = IDL.Record({
'user_groups' : IDL.Vec(UUID),
'auth_scope' : AuthScope,
Expand Down Expand Up @@ -617,6 +628,7 @@ export const idlFactory = ({ IDL }) => {
'AddUserGroup' : AddUserGroupOperation,
'EditPermission' : EditPermissionOperation,
'SnapshotExternalCanister' : SnapshotExternalCanisterOperation,
'PruneExternalCanister' : PruneExternalCanisterOperation,
'ConfigureExternalCanister' : ConfigureExternalCanisterOperation,
'ChangeExternalCanister' : ChangeExternalCanisterOperation,
'AddUser' : AddUserOperation,
Expand Down Expand Up @@ -764,6 +776,7 @@ export const idlFactory = ({ IDL }) => {
'AddUserGroup' : AddUserGroupOperationInput,
'EditPermission' : EditPermissionOperationInput,
'SnapshotExternalCanister' : SnapshotExternalCanisterOperationInput,
'PruneExternalCanister' : PruneExternalCanisterOperationInput,
'ConfigureExternalCanister' : ConfigureExternalCanisterOperationInput,
'ChangeExternalCanister' : ChangeExternalCanisterOperationInput,
'AddUser' : AddUserOperationInput,
Expand Down Expand Up @@ -962,6 +975,7 @@ export const idlFactory = ({ IDL }) => {
'AddUserGroup' : IDL.Null,
'EditPermission' : IDL.Null,
'SnapshotExternalCanister' : IDL.Opt(IDL.Principal),
'PruneExternalCanister' : IDL.Opt(IDL.Principal),
'ConfigureExternalCanister' : IDL.Opt(IDL.Principal),
'ChangeExternalCanister' : IDL.Opt(IDL.Principal),
'AddUser' : IDL.Null,
Expand Down Expand Up @@ -1196,6 +1210,7 @@ export const idlFactory = ({ IDL }) => {
'AddUserGroup' : IDL.Null,
'EditPermission' : IDL.Null,
'SnapshotExternalCanister' : IDL.Null,
'PruneExternalCanister' : IDL.Null,
'ConfigureExternalCanister' : IDL.Null,
'ChangeExternalCanister' : IDL.Null,
'AddUser' : IDL.Null,
Expand Down
23 changes: 23 additions & 0 deletions core/station/api/spec.did
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,21 @@ type RestoreExternalCanisterOperation = record {
input : RestoreExternalCanisterOperationInput;
};

type PruneExternalCanisterOperationInput = record {
// The canister to prune.
canister_id : principal;
// The resource to prune.
prune : variant {
chunk_store;
snapshot : text;
state;
};
};

type PruneExternalCanisterOperation = record {
input : PruneExternalCanisterOperationInput;
};

type EditPermissionOperationInput = record {
// The updated resource that this policy will apply to.
resource : Resource;
Expand Down Expand Up @@ -942,6 +957,8 @@ type RequestOperation = variant {
SnapshotExternalCanister : SnapshotExternalCanisterOperation;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister : RestoreExternalCanisterOperation;
// An operation for pruning an external canister.
PruneExternalCanister : PruneExternalCanisterOperation;
// An operation for editing an permission.
EditPermission : EditPermissionOperation;
// An operation for adding a request policy.
Expand Down Expand Up @@ -995,6 +1012,8 @@ type RequestOperationInput = variant {
SnapshotExternalCanister : SnapshotExternalCanisterOperationInput;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister : RestoreExternalCanisterOperationInput;
// An operation for pruning an external canister.
PruneExternalCanister : PruneExternalCanisterOperationInput;
// An operation for editing an permission.
EditPermission : EditPermissionOperationInput;
// An operation for adding a request policy.
Expand Down Expand Up @@ -1048,6 +1067,8 @@ type RequestOperationType = variant {
SnapshotExternalCanister;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister;
// An operation for pruning an external canister.
PruneExternalCanister;
// An operation for editing an permission.
EditPermission;
// An operation for adding a request policy.
Expand Down Expand Up @@ -1200,6 +1221,8 @@ type ListRequestsOperationType = variant {
SnapshotExternalCanister : opt principal;
// An operation for restoring an external canister from a snapshot.
RestoreExternalCanister : opt principal;
// An operation for pruning an external canister.
PruneExternalCanister : opt principal;
// An operation for editing an permission.
EditPermission;
// An operation for adding a request policy.
Expand Down
21 changes: 21 additions & 0 deletions core/station/api/src/external_canister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,3 +405,24 @@ pub struct RestoreExternalCanisterOperationInput {
pub struct RestoreExternalCanisterOperationDTO {
pub input: RestoreExternalCanisterOperationInput,
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
pub enum PruneExternalCanisterResourceDTO {
#[serde(rename = "snapshot")]
Snapshot(String),
#[serde(rename = "chunk_store")]
ChunkStore,
#[serde(rename = "state")]
State,
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
pub struct PruneExternalCanisterOperationInput {
pub canister_id: Principal,
pub prune: PruneExternalCanisterResourceDTO,
}

#[derive(CandidType, serde::Serialize, Deserialize, Debug, Clone)]
pub struct PruneExternalCanisterOperationDTO {
pub input: PruneExternalCanisterOperationInput,
}
5 changes: 5 additions & 0 deletions core/station/api/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
EditUserGroupOperationInput, EditUserOperationDTO, EditUserOperationInput,
FundExternalCanisterOperationDTO, FundExternalCanisterOperationInput,
ManageSystemInfoOperationDTO, ManageSystemInfoOperationInput, PaginationInput,
PruneExternalCanisterOperationDTO, PruneExternalCanisterOperationInput,
RemoveAddressBookEntryOperationDTO, RemoveAddressBookEntryOperationInput,
RemoveUserGroupOperationDTO, RemoveUserGroupOperationInput, RequestEvaluationResultDTO,
RequestPolicyRuleDTO, RequestSpecifierDTO, RestoreExternalCanisterOperationDTO,
Expand Down Expand Up @@ -82,6 +83,7 @@ pub enum RequestOperationDTO {
FundExternalCanister(Box<FundExternalCanisterOperationDTO>),
SnapshotExternalCanister(Box<SnapshotExternalCanisterOperationDTO>),
RestoreExternalCanister(Box<RestoreExternalCanisterOperationDTO>),
PruneExternalCanister(Box<PruneExternalCanisterOperationDTO>),
EditPermission(Box<EditPermissionOperationDTO>),
AddRequestPolicy(Box<AddRequestPolicyOperationDTO>),
EditRequestPolicy(Box<EditRequestPolicyOperationDTO>),
Expand Down Expand Up @@ -111,6 +113,7 @@ pub enum RequestOperationInput {
FundExternalCanister(FundExternalCanisterOperationInput),
SnapshotExternalCanister(SnapshotExternalCanisterOperationInput),
RestoreExternalCanister(RestoreExternalCanisterOperationInput),
PruneExternalCanister(PruneExternalCanisterOperationInput),
EditPermission(EditPermissionOperationInput),
AddRequestPolicy(AddRequestPolicyOperationInput),
EditRequestPolicy(EditRequestPolicyOperationInput),
Expand Down Expand Up @@ -139,6 +142,7 @@ pub enum RequestOperationTypeDTO {
FundExternalCanister,
SnapshotExternalCanister,
RestoreExternalCanister,
PruneExternalCanister,
EditPermission,
AddRequestPolicy,
EditRequestPolicy,
Expand Down Expand Up @@ -167,6 +171,7 @@ pub enum ListRequestsOperationTypeDTO {
FundExternalCanister(Option<Principal>),
SnapshotExternalCanister(Option<Principal>),
RestoreExternalCanister(Option<Principal>),
PruneExternalCanister(Option<Principal>),
EditPermission,
AddRequestPolicy,
EditRequestPolicy,
Expand Down
15 changes: 15 additions & 0 deletions core/station/impl/src/factories/requests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mod edit_user;
mod edit_user_group;
mod fund_external_canister;
mod manage_system_info;
mod prune_external_canister;
mod remove_address_book_entry;
mod remove_request_policy;
mod remove_user_group;
Expand Down Expand Up @@ -64,6 +65,8 @@ use self::{
edit_request_policy::{EditRequestPolicyRequestCreate, EditRequestPolicyRequestExecute},
edit_user::{EditUserRequestCreate, EditUserRequestExecute},
edit_user_group::{EditUserGroupRequestCreate, EditUserGroupRequestExecute},
prune_external_canister::PruneExternalCanisterRequestCreate,
prune_external_canister::PruneExternalCanisterRequestExecute,
remove_address_book_entry::{
RemoveAddressBookEntryRequestCreate, RemoveAddressBookEntryRequestExecute,
},
Expand Down Expand Up @@ -235,6 +238,12 @@ impl RequestFactory {
.create(id, requested_by_user, input.clone(), operation.clone())
.await
}
RequestOperationInput::PruneExternalCanister(operation) => {
let creator = Box::new(PruneExternalCanisterRequestCreate {});
creator
.create(id, requested_by_user, input.clone(), operation.clone())
.await
}
RequestOperationInput::EditPermission(operation) => {
let creator = Box::new(EditPermissionRequestCreate {});
creator
Expand Down Expand Up @@ -361,6 +370,12 @@ impl RequestFactory {
Arc::clone(&CHANGE_CANISTER_SERVICE),
))
}
RequestOperation::PruneExternalCanister(operation) => {
Box::new(PruneExternalCanisterRequestExecute::new(
operation,
Arc::clone(&CHANGE_CANISTER_SERVICE),
))
}
RequestOperation::EditPermission(operation) => {
Box::new(EditPermissionRequestExecute::new(
request,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use super::{Create, Execute, RequestExecuteStage};
use crate::{
errors::{RequestError, RequestExecuteError},
models::{PruneExternalCanisterOperation, Request, RequestOperation},
services::ChangeCanisterService,
};
use async_trait::async_trait;
use orbit_essentials::types::UUID;
use station_api::{CreateRequestInput, PruneExternalCanisterOperationInput};
use std::sync::Arc;

pub struct PruneExternalCanisterRequestCreate;

#[async_trait]
impl Create<PruneExternalCanisterOperationInput> for PruneExternalCanisterRequestCreate {
async fn create(
&self,
request_id: UUID,
requested_by_user: UUID,
input: CreateRequestInput,
operation_input: PruneExternalCanisterOperationInput,
) -> Result<Request, RequestError> {
let request = Request::from_request_creation_input(
request_id,
requested_by_user,
input,
RequestOperation::PruneExternalCanister(PruneExternalCanisterOperation {
input: operation_input.into(),
}),
"Prune canister".to_string(),
);

Ok(request)
}
}

pub struct PruneExternalCanisterRequestExecute<'o> {
operation: &'o PruneExternalCanisterOperation,
change_canister_service: Arc<ChangeCanisterService>,
}

impl<'o> PruneExternalCanisterRequestExecute<'o> {
pub fn new(
operation: &'o PruneExternalCanisterOperation,
change_canister_service: Arc<ChangeCanisterService>,
) -> Self {
Self {
operation,
change_canister_service,
}
}
}

#[async_trait]
impl Execute for PruneExternalCanisterRequestExecute<'_> {
async fn execute(&self) -> Result<RequestExecuteStage, RequestExecuteError> {
self.change_canister_service
.prune_canister(
self.operation.input.canister_id,
self.operation.input.prune.clone(),
)
.await
.map_err(|err| RequestExecuteError::Failed {
reason: format!(
"failed to prune {} on external canister {}: {}",
self.operation.input.canister_id, self.operation.input.prune, err
),
})?;

Ok(RequestExecuteStage::Completed(
RequestOperation::PruneExternalCanister(self.operation.clone()),
))
}
}
Loading

0 comments on commit 65cba91

Please sign in to comment.