Skip to content

Commit 8cdc0ae

Browse files
committed
support external manifests for network and environment
1 parent d67f8a5 commit 8cdc0ae

File tree

3 files changed

+122
-85
lines changed

3 files changed

+122
-85
lines changed

crates/icp/src/manifest/mod.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ pub mod project;
1818
pub(crate) mod recipe;
1919
pub(crate) mod serde_helpers;
2020

21-
pub use {
22-
canister::CanisterManifest,
23-
environment::EnvironmentManifest,
24-
network::NetworkManifest,
25-
};
21+
pub use {canister::CanisterManifest, environment::EnvironmentManifest, network::NetworkManifest};
2622

2723
pub const PROJECT_MANIFEST: &str = "icp.yaml";
2824
pub const CANISTER_MANIFEST: &str = "canister.yaml";
@@ -46,33 +42,33 @@ impl Default for Canisters {
4642
impl Default for Networks {
4743
fn default() -> Self {
4844
Networks::Networks(vec![
49-
NetworkManifest {
45+
Item::Manifest(NetworkManifest {
5046
name: "local".to_string(),
5147
configuration: Configuration::Managed {
5248
managed: Managed::default(),
5349
},
54-
},
55-
NetworkManifest {
50+
}),
51+
Item::Manifest(NetworkManifest {
5652
name: "mainnet".to_string(),
5753
configuration: Configuration::Connected {
5854
connected: Connected {
5955
url: IC_MAINNET_NETWORK_URL.to_string(),
6056
root_key: None,
6157
},
6258
},
63-
},
59+
}),
6460
])
6561
}
6662
}
6763

6864
impl Default for Environments {
6965
fn default() -> Self {
70-
Environments::Environments(vec![EnvironmentManifest {
66+
Environments::Environments(vec![Item::Manifest(EnvironmentManifest {
7167
name: "local".to_string(),
7268
network: "local".to_string(),
7369
canisters: CanisterSelection::Everything,
7470
settings: None,
75-
}])
71+
})])
7672
}
7773
}
7874

@@ -155,7 +151,7 @@ mod tests {
155151
assert_eq!(
156152
Networks::default(),
157153
Networks::Networks(vec![
158-
NetworkManifest {
154+
Item::Manifest(NetworkManifest {
159155
name: "local".to_string(),
160156
configuration: Configuration::Managed {
161157
managed: Managed {
@@ -165,16 +161,16 @@ mod tests {
165161
},
166162
}
167163
},
168-
},
169-
NetworkManifest {
164+
}),
165+
Item::Manifest(NetworkManifest {
170166
name: "mainnet".to_string(),
171167
configuration: Configuration::Connected {
172168
connected: Connected {
173169
url: "https://icp-api.io".to_string(),
174170
root_key: None,
175171
}
176172
},
177-
},
173+
}),
178174
])
179175
);
180176

@@ -185,12 +181,12 @@ mod tests {
185181
fn default_environments() -> Result<(), Error> {
186182
assert_eq!(
187183
Environments::default(),
188-
Environments::Environments(vec![EnvironmentManifest {
184+
Environments::Environments(vec![Item::Manifest(EnvironmentManifest {
189185
name: "local".to_string(),
190186
network: "local".to_string(),
191187
canisters: CanisterSelection::Everything,
192188
settings: None,
193-
}])
189+
})])
194190
);
195191

196192
Ok(())

crates/icp/src/manifest/project.rs

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,9 @@ impl<'de> Deserialize<'de> for ProjectManifest {
259259
}
260260

261261
[
262-
Into::<Vec<Item<EnvironmentManifest>>>::into(Environments::default()),
262+
Into::<Vec<Item<EnvironmentManifest>>>::into(
263+
Environments::default(),
264+
),
263265
environments,
264266
]
265267
.concat()
@@ -311,7 +313,8 @@ impl<'de> Deserialize<'de> for ProjectManifest {
311313
.remove(&networks_key)
312314
.ok_or_else(|| Error::custom("'networks' key does not exist"))?
313315
{
314-
let mut networks: Vec<Item<NetworkManifest>> = Vec::with_capacity(seq.len());
316+
let mut networks: Vec<Item<NetworkManifest>> =
317+
Vec::with_capacity(seq.len());
315318

316319
for v in seq {
317320
let network_manifest = serde_yaml::from_value(v).map_err(|e| {
@@ -564,12 +567,14 @@ mod tests {
564567
ProjectManifest {
565568
canisters: Canisters::default().into(),
566569
networks: Networks::default().into(),
567-
environments: Environments::Environments(vec![Item::Manifest(EnvironmentManifest {
568-
name: "my-environment".to_string(),
569-
network: "my-network".to_string(),
570-
canisters: CanisterSelection::Named(vec!["my-canister".to_string()]),
571-
settings: None,
572-
})])
570+
environments: Environments::Environments(vec![Item::Manifest(
571+
EnvironmentManifest {
572+
name: "my-environment".to_string(),
573+
network: "my-network".to_string(),
574+
canisters: CanisterSelection::Named(vec!["my-canister".to_string()]),
575+
settings: None,
576+
}
577+
)])
573578
.with_defaults()
574579
.into(),
575580
},
@@ -590,12 +595,14 @@ mod tests {
590595
ProjectManifest {
591596
canisters: Canisters::default().into(),
592597
networks: Networks::default().into(),
593-
environments: Environments::Environments(vec![Item::Manifest(EnvironmentManifest {
594-
name: "my-environment".to_string(),
595-
network: "my-network".to_string(),
596-
canisters: CanisterSelection::Named(vec!["my-canister".to_string()]),
597-
settings: None,
598-
})])
598+
environments: Environments::Environments(vec![Item::Manifest(
599+
EnvironmentManifest {
600+
name: "my-environment".to_string(),
601+
network: "my-network".to_string(),
602+
canisters: CanisterSelection::Named(vec!["my-canister".to_string()]),
603+
settings: None,
604+
}
605+
)])
599606
.with_defaults()
600607
.into(),
601608
},
@@ -665,27 +672,29 @@ mod tests {
665672
ProjectManifest {
666673
canisters: Canisters::default().into(),
667674
networks: Networks::default().into(),
668-
environments: Environments::Environments(vec![Item::Manifest(EnvironmentManifest {
669-
name: "my-environment".to_string(),
670-
network: "local".to_string(),
671-
canisters: CanisterSelection::Everything,
672-
settings: Some(HashMap::from([
673-
(
674-
"canister-1".to_string(),
675-
Settings {
676-
compute_allocation: Some(1),
677-
..Default::default()
678-
}
679-
),
680-
(
681-
"canister-2".to_string(),
682-
Settings {
683-
compute_allocation: Some(2),
684-
..Default::default()
685-
}
686-
)
687-
])),
688-
})])
675+
environments: Environments::Environments(vec![Item::Manifest(
676+
EnvironmentManifest {
677+
name: "my-environment".to_string(),
678+
network: "local".to_string(),
679+
canisters: CanisterSelection::Everything,
680+
settings: Some(HashMap::from([
681+
(
682+
"canister-1".to_string(),
683+
Settings {
684+
compute_allocation: Some(1),
685+
..Default::default()
686+
}
687+
),
688+
(
689+
"canister-2".to_string(),
690+
Settings {
691+
compute_allocation: Some(2),
692+
..Default::default()
693+
}
694+
)
695+
])),
696+
}
697+
)])
689698
.with_defaults()
690699
.into(),
691700
},

crates/icp/src/project.rs

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{
66

77
use anyhow::Context;
88
use async_trait::async_trait;
9+
use serde::de::DeserializeOwned;
910

1011
use crate::{
1112
Canister, Environment, LoadManifest, LoadPath, Network, Project,
@@ -21,11 +22,11 @@ use crate::{
2122

2223
#[derive(Debug, thiserror::Error)]
2324
pub enum LoadPathError {
24-
#[error("failed to read canister manifest")]
25-
Read,
25+
#[error("failed to read manifest at {0}")]
26+
Read(String),
2627

27-
#[error("failed to deserialize canister manifest")]
28-
Deserialize,
28+
#[error("failed to deserialize manifest at {0}")]
29+
Deserialize(String),
2930

3031
#[error(transparent)]
3132
Unexpected(#[from] anyhow::Error),
@@ -34,14 +35,17 @@ pub enum LoadPathError {
3435
pub struct PathLoader;
3536

3637
#[async_trait]
37-
impl LoadPath<ProjectManifest, LoadPathError> for PathLoader {
38-
async fn load(&self, path: &Path) -> Result<ProjectManifest, LoadPathError> {
38+
impl<T> LoadPath<T, LoadPathError> for PathLoader
39+
where
40+
T: DeserializeOwned + Send + 'static,
41+
{
42+
async fn load(&self, path: &Path) -> Result<T, LoadPathError> {
3943
// Read file
40-
let mbs = read(path).context(LoadPathError::Read)?;
44+
let mbs = read(path).context(LoadPathError::Read(path.to_string()))?;
4145

42-
// Load YAML
43-
let m =
44-
serde_yaml::from_slice::<ProjectManifest>(&mbs).context(LoadPathError::Deserialize)?;
46+
// Deserialize YAML into any T
47+
let m = serde_yaml::from_slice::<T>(&mbs)
48+
.context(LoadPathError::Deserialize(path.to_string()))?;
4549

4650
Ok(m)
4751
}
@@ -216,7 +220,7 @@ impl LoadManifest<ProjectManifest, Project, LoadManifestError> for ManifestLoade
216220
let mut networks: HashMap<String, Network> = HashMap::new();
217221

218222
for i in &m.networks {
219-
let ms = match i {
223+
let m = match i {
220224
Item::Path(path) => {
221225
let path = pdir.join(path);
222226
if !path.exists() || !path.is_file() {
@@ -225,34 +229,62 @@ impl LoadManifest<ProjectManifest, Project, LoadManifestError> for ManifestLoade
225229
path: path.to_string(),
226230
});
227231
}
228-
self.network.load(path).await.context(LoadManifestError::Failed { kind: "network".to_string(), path: path.to_string() })?
229-
230-
},
231-
Item::Manifest(ms) => ms,
232+
let loader = PathLoader;
233+
loader
234+
.load(&path)
235+
.await
236+
.context(LoadManifestError::Failed {
237+
kind: "network".to_string(),
238+
path: path.to_string(),
239+
})?
240+
}
241+
Item::Manifest(ms) => ms.clone(),
232242
};
233-
//match networks.entry(m.name.to_owned()) {
234-
// // Duplicate
235-
// Entry::Occupied(e) => {
236-
// return Err(LoadManifestError::Duplicate {
237-
// kind: "network".to_string(),
238-
// name: e.key().to_owned(),
239-
// });
240-
// }
241-
242-
// // Ok
243-
// Entry::Vacant(e) => {
244-
// e.insert(Network {
245-
// name: m.name.to_owned(),
246-
// configuration: m.configuration.to_owned(),
247-
// });
248-
// }
249-
//}
243+
244+
match networks.entry(m.name.to_owned()) {
245+
// Duplicate
246+
Entry::Occupied(e) => {
247+
return Err(LoadManifestError::Duplicate {
248+
kind: "network".to_string(),
249+
name: e.key().to_owned(),
250+
});
251+
}
252+
253+
// Ok
254+
Entry::Vacant(e) => {
255+
e.insert(Network {
256+
name: m.name.to_owned(),
257+
configuration: m.configuration.to_owned(),
258+
});
259+
}
260+
}
250261
}
251262

252263
// Environments
253264
let mut environments: HashMap<String, Environment> = HashMap::new();
254265

255-
for m in &m.environments {
266+
for i in &m.environments {
267+
let m = match i {
268+
Item::Path(path) => {
269+
let path = pdir.join(path);
270+
if !path.exists() || !path.is_file() {
271+
return Err(LoadManifestError::NotFound {
272+
kind: "environment".to_string(),
273+
path: path.to_string(),
274+
});
275+
}
276+
let loader = PathLoader;
277+
loader
278+
.load(&path)
279+
.await
280+
.context(LoadManifestError::Failed {
281+
kind: "environment".to_string(),
282+
path: path.to_string(),
283+
})?
284+
}
285+
Item::Manifest(ms) => ms.clone(),
286+
};
287+
256288
match environments.entry(m.name.to_owned()) {
257289
// Duplicate
258290
Entry::Occupied(e) => {

0 commit comments

Comments
 (0)