Skip to main content

oasis_core_runtime/host/
bundle_manager.rs

1use std::collections::BTreeMap;
2
3use async_trait::async_trait;
4
5use crate::{common::crypto::hash::Hash, protocol::Protocol};
6
7use super::{host_rpc_call, Error};
8
9/// Name of the local RPC endpoint for the bundle manager.
10pub const LOCAL_RPC_ENDPOINT_BUNDLE_MANAGER: &str = "bundle-manager";
11
12/// Name of the BundleWrite method.
13pub const METHOD_BUNDLE_WRITE: &str = "BundleWrite";
14/// Name of the BundleAdd method.
15pub const METHOD_BUNDLE_ADD: &str = "BundleAdd";
16/// Name of the BundleRemove method.
17pub const METHOD_BUNDLE_REMOVE: &str = "BundleRemove";
18/// Name of the BundleList method.
19pub const METHOD_BUNDLE_LIST: &str = "BundleList";
20
21/// Name of the special label that identifies the instance.
22pub const LABEL_INSTANCE_ID: &str = "net.oasis.instance_id";
23
24/// Bundle manager interface.
25#[allow(clippy::double_must_use)]
26#[async_trait]
27pub trait BundleManager: Send + Sync {
28    /// Request to host to write a chunk of the bundle to a temporary file.
29    ///
30    /// The `PermissionBundleAdd` permission is required to call this method.
31    async fn bundle_write(&self, args: BundleWriteRequest) -> Result<BundleWriteResponse, Error>;
32
33    /// Request to host to add a specific bundle to the host.
34    ///
35    /// The `PermissionBundleAdd` permission is required to call this method.
36    async fn bundle_add(&self, args: BundleAddRequest) -> Result<BundleAddResponse, Error>;
37
38    /// Request to host to remove a specific component. Only components added by this component
39    /// can be removed.
40    ///
41    /// The `PermissionBundleRemove` permission is required to call this method.
42    async fn bundle_remove(&self, args: BundleRemoveRequest)
43        -> Result<BundleRemoveResponse, Error>;
44
45    /// Request to host to list all bundles.
46    ///
47    /// The `PermissionBundleAdd` permission is required to call this method.
48    async fn bundle_list(&self, args: BundleListRequest) -> Result<BundleListResponse, Error>;
49}
50
51#[allow(clippy::double_must_use)]
52#[async_trait]
53impl BundleManager for Protocol {
54    async fn bundle_write(&self, args: BundleWriteRequest) -> Result<BundleWriteResponse, Error> {
55        host_rpc_call(
56            self,
57            LOCAL_RPC_ENDPOINT_BUNDLE_MANAGER,
58            METHOD_BUNDLE_WRITE,
59            args,
60        )
61        .await
62    }
63
64    async fn bundle_add(&self, args: BundleAddRequest) -> Result<BundleAddResponse, Error> {
65        host_rpc_call(
66            self,
67            LOCAL_RPC_ENDPOINT_BUNDLE_MANAGER,
68            METHOD_BUNDLE_ADD,
69            args,
70        )
71        .await
72    }
73
74    async fn bundle_remove(
75        &self,
76        args: BundleRemoveRequest,
77    ) -> Result<BundleRemoveResponse, Error> {
78        host_rpc_call(
79            self,
80            LOCAL_RPC_ENDPOINT_BUNDLE_MANAGER,
81            METHOD_BUNDLE_REMOVE,
82            args,
83        )
84        .await
85    }
86
87    async fn bundle_list(&self, args: BundleListRequest) -> Result<BundleListResponse, Error> {
88        host_rpc_call(
89            self,
90            LOCAL_RPC_ENDPOINT_BUNDLE_MANAGER,
91            METHOD_BUNDLE_LIST,
92            args,
93        )
94        .await
95    }
96}
97
98/// Request to host to write a chunk of the bundle to a temporary file.
99///
100/// The `PermissionBundleAdd` permission is required to call this method.
101#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
102pub struct BundleWriteRequest {
103    /// Temporary file name to use on the host while writing the bundle.
104    pub temporary_name: String,
105    /// Optional flag which specifies that the temporary file should be recreated. If the file
106    /// exists and this flag is set to true, it will be truncated. If the flag is set to false, any
107    /// content will be appended to the existing file.
108    pub create: bool,
109    /// Data that should be appended to the temporary file.
110    pub data: Vec<u8>,
111}
112
113/// Response form the BundleWrite method.
114#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
115pub struct BundleWriteResponse {}
116
117/// Request to host to add a specific bundle to the host.
118///
119/// The `PermissionBundleAdd` permission is required to call this method.
120#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
121pub struct BundleAddRequest {
122    /// Temporary file name to read the bundle from. The file must have previously been created by
123    /// using `BundleWriteRequest`.
124    ///
125    /// The file must be a valid bundle.
126    pub temporary_name: String,
127    /// Expected hash of the manifest contained inside the bundle.
128    pub manifest_hash: Hash,
129    /// Labels to tag the bundle with.
130    ///
131    /// Note that the host will assign a random component identifier to these components, so one
132    /// should use labels to later be able to find them.
133    ///
134    /// Use the special `LABEL_INSTANCE_ID` label to specify a deterministic instance ID.
135    pub labels: BTreeMap<String, String>,
136    /// Volumes to attach to the bundle.
137    pub volumes: BTreeMap<String, String>,
138}
139
140/// Response form the BundleAdd method.
141#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
142pub struct BundleAddResponse {}
143
144/// Request to host to remove a specific component. Only components added by this component can be
145/// removed.
146///
147/// The `PermissionBundleRemove` permission is required to call this method.
148#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
149pub struct BundleRemoveRequest {
150    /// Labels to filter the components by.
151    pub labels: BTreeMap<String, String>,
152}
153
154/// Response form the BundleRemove method.
155#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
156pub struct BundleRemoveResponse {}
157
158/// Request to host to list all bundles.
159///
160/// The `PermissionBundleAdd` permission is required to call this method.
161#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
162pub struct BundleListRequest {
163    /// Labels to filter the components by.
164    pub labels: BTreeMap<String, String>,
165}
166
167/// Response from host to list all bundles.
168#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
169pub struct BundleListResponse {
170    /// The resulting bundles.
171    #[cbor(optional)]
172    pub bundles: Vec<BundleInfo>,
173}
174
175/// Bundle information.
176#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
177pub struct BundleInfo {
178    /// Hash of the manifest.
179    pub manifest_hash: Hash,
180    /// List of all components in this bundle.
181    pub components: Vec<ComponentInfo>,
182    /// Labels assigned to this bundle.
183    pub labels: BTreeMap<String, String>,
184}
185
186/// Component information.
187#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
188pub struct ComponentInfo {
189    /// Component name.
190    pub name: String,
191}