This repository has been archived by the owner on Feb 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 267
Run hApp-bundles during develpment with hc run
#1939
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
ce6fb4a
WIP added HappBundle struct and conversion to conductor Configuration
lucksus fe128cd
rustfmt
lucksus 91409e5
WIP loading bundle file
lucksus b6fbdfa
Merge branch 'develop' into hc-run-bundles
lucksus 056bccf
Fix build
lucksus 13fb9d4
Fix typos and property names to be able to read existing bundle files
lucksus f9c1714
From -> TryFrom and run checks
lucksus 01f2afe
Make HappBundleUi::id optional
lucksus cd92743
Only check for "file:" without slashes since "file:./something" is al…
lucksus 0929aac
Actually run conductor with config from bundle
lucksus 306d2db
Start static web servers on hc run
lucksus 9b41188
Don't rerout to root as it breaks the _dna_connections.js route
lucksus 8337b27
Use provided port for bundles too in hc run
lucksus 41bd0a6
Move HappBundle into conductor_lib
lucksus 3380b1a
Extract port util funcrtions into own file
lucksus b931106
rustfmt
lucksus 43657fb
Get free ports for interfaces and static UI servers in hc run bundle
lucksus b96ecb1
rustfmt
lucksus 2ba2125
Wire up persist flag
lucksus b19b36d
Remove unused interface_type from bundle case
lucksus 01d8467
rustfmt
lucksus 3cbb859
Merge branch 'develop' into hc-run-bundles
lucksus 636d3fe
clippy
lucksus e2d7984
changelog
lucksus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
use crate::{config::*, port_utils::get_free_port}; | ||
use boolinator::Boolinator; | ||
use std::collections::HashMap; | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub struct HappBundle { | ||
pub instances: Vec<HappBundleInstance>, | ||
pub bridges: Vec<Bridge>, | ||
#[serde(rename = "UIs")] | ||
pub uis: Vec<HappBundleUi>, | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub struct HappBundleInstance { | ||
pub name: String, | ||
pub id: String, | ||
pub dna_hash: String, | ||
pub uri: String, | ||
pub dna_properties: Option<HashMap<String, String>>, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Debug)] | ||
pub struct HappBundleUi { | ||
pub name: String, | ||
pub id: Option<String>, | ||
pub uri: String, | ||
pub instance_references: Vec<HappBundleInstanceReference>, | ||
} | ||
|
||
impl HappBundleUi { | ||
pub fn id(&self) -> String { | ||
self.id.clone().unwrap_or_else(|| String::from("")) | ||
} | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Debug)] | ||
pub struct HappBundleInstanceReference { | ||
pub ui_handle: String, | ||
pub instance_id: String, | ||
} | ||
|
||
impl HappBundle { | ||
pub fn id_references_are_consistent(&self) -> Result<(), String> { | ||
for bridge in self.bridges.iter() { | ||
for id in vec![bridge.callee_id.clone(), bridge.caller_id.clone()] { | ||
self.instances.iter().find(|i| i.id == id).ok_or_else(|| { | ||
format!( | ||
"No instance with ID {} referenced in bridge {:?}", | ||
id, bridge | ||
) | ||
})?; | ||
} | ||
} | ||
|
||
for ui in self.uis.iter() { | ||
for reference in ui.instance_references.iter() { | ||
self.instances | ||
.iter() | ||
.find(|i| i.id == reference.instance_id) | ||
.ok_or_else(|| { | ||
format!( | ||
"No instance with ID {} referenced in UI {:?}", | ||
reference.instance_id, ui | ||
) | ||
})?; | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub fn only_file_uris(&self) -> Result<(), String> { | ||
for instance in self.instances.iter() { | ||
instance.uri.starts_with("file:").ok_or_else(|| { | ||
format!( | ||
"Instance {} uses non-file URI which is not supported in `hc run`", | ||
instance.id | ||
) | ||
})?; | ||
} | ||
|
||
for ui in self.uis.iter() { | ||
ui.uri.starts_with("dir:").ok_or_else(|| { | ||
format!( | ||
"UI {} uses non-dir URI which is not supported in `hc run`", | ||
ui.id() | ||
) | ||
})?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn build_conductor_config( | ||
&self, | ||
ui_port: u16, | ||
agent_config: AgentConfiguration, | ||
storage: StorageConfiguration, | ||
network: Option<NetworkConfig>, | ||
logger: LoggerConfiguration, | ||
) -> Result<Configuration, String> { | ||
self.id_references_are_consistent()?; | ||
self.only_file_uris()?; | ||
|
||
let dnas = self | ||
.instances | ||
.iter() | ||
.map(|happ_instance| { | ||
// splitting off "file://" | ||
let file = happ_instance.uri.clone().split_off(5); | ||
DnaConfiguration { | ||
id: happ_instance.id.clone(), | ||
file, | ||
hash: happ_instance.dna_hash.clone(), | ||
uuid: None, | ||
} | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let instances = self | ||
.instances | ||
.iter() | ||
.map(|happ_instance| InstanceConfiguration { | ||
id: happ_instance.id.clone(), | ||
dna: happ_instance.id.clone(), | ||
agent: agent_config.id.clone(), | ||
storage: storage.clone(), | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let mut interfaces = Vec::new(); | ||
let mut ui_bundles = Vec::new(); | ||
let mut ui_interfaces = Vec::new(); | ||
|
||
const MIN_INTERFACE_PORT: u16 = 50000; | ||
const MAX_INTERFACE_PORT: u16 = 60000; | ||
let mut next_interface_port: u16 = MIN_INTERFACE_PORT; | ||
let mut next_ui_port = ui_port; | ||
|
||
for ui in self.uis.iter() { | ||
let port = get_free_port(next_interface_port..MAX_INTERFACE_PORT) | ||
.ok_or_else(|| String::from("Couldn't acquire free port"))?; | ||
next_interface_port = port + 1; | ||
interfaces.push(InterfaceConfiguration { | ||
id: ui.id(), | ||
driver: InterfaceDriver::Websocket { port }, | ||
admin: false, | ||
instances: ui | ||
.instance_references | ||
.iter() | ||
.map(|ui_ref| InstanceReferenceConfiguration { | ||
id: ui_ref.instance_id.clone(), | ||
alias: Some(ui_ref.ui_handle.clone()), | ||
}) | ||
.collect(), | ||
}); | ||
|
||
ui_bundles.push(UiBundleConfiguration { | ||
id: ui.id(), | ||
root_dir: ui.uri.clone().split_off(4), // splitting off "dir://" | ||
hash: None, | ||
}); | ||
|
||
let port = get_free_port(next_ui_port..MIN_INTERFACE_PORT - 1) | ||
.ok_or_else(|| String::from("Couldn't acquire free port"))?; | ||
next_ui_port = port + 1; | ||
ui_interfaces.push(UiInterfaceConfiguration { | ||
id: ui.id(), | ||
bundle: ui.id(), | ||
port, | ||
dna_interface: Some(ui.id()), | ||
reroute_to_root: false, | ||
bind_address: String::from("127.0.0.1"), | ||
}); | ||
} | ||
|
||
Ok(Configuration { | ||
agents: vec![agent_config], | ||
dnas, | ||
instances, | ||
bridges: self.bridges.clone(), | ||
interfaces, | ||
ui_bundles, | ||
ui_interfaces, | ||
network, | ||
logger, | ||
..Default::default() | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. It would be really easy to wasm-bindgen this integrity check code for holoscape so it isn't duped in Rust and Javascript