mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-12 06:45:32 +00:00
Introduce REPL for testing (#14)
This commit is contained in:
parent
c06dddd5ae
commit
7254fe7e8c
158
Cargo.lock
generated
158
Cargo.lock
generated
@ -82,6 +82,12 @@ dependencies = [
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.1"
|
||||
@ -99,10 +105,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "0.3.5"
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59f88a20f7dc23e3896bcbd85add056543c87215de721468b90e0c85d5a9f365"
|
||||
checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce4f9586c9a3151c4b49b19e82ba163dd073614dd057e53c969e1a4db5b52720"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
@ -133,9 +150,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.1"
|
||||
version = "2.33.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
|
||||
checksum = "10040cdf04294b565d9e0319955430099ec3813a64c952b86a41200ad714ae48"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
@ -313,6 +330,27 @@ dependencies = [
|
||||
"generic-array 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cbcf9241d9e8d106295bd496bbe2e9cffd5fa098f2a8c9e2bbcbf09773c11a8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c60f7b8a8953926148223260454befb50c751d3c50e1c178c4fd1ace4083c9a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "effector"
|
||||
version = "0.1.0"
|
||||
@ -431,6 +469,19 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fce-repl"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"fluence-app-service",
|
||||
"rustop",
|
||||
"rustyline",
|
||||
"serde_json",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fce-wit-generator"
|
||||
version = "0.1.1"
|
||||
@ -466,7 +517,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#7018a64c29278a673e543867e691f74b3d652288"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#8418111074644a1bc197315060facd34778099de"
|
||||
dependencies = [
|
||||
"fluence-sdk-macro",
|
||||
"fluence-sdk-main",
|
||||
@ -476,16 +527,10 @@ dependencies = [
|
||||
name = "fluence-app-service"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cmd_lib",
|
||||
"fluence-faas",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"toml",
|
||||
"wasmer-runtime-core-fl",
|
||||
"wasmer-runtime-fl",
|
||||
"wasmer-wasi-fl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -507,7 +552,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence-sdk-macro"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#7018a64c29278a673e543867e691f74b3d652288"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#8418111074644a1bc197315060facd34778099de"
|
||||
dependencies = [
|
||||
"fluence-sdk-wit 0.2.0 (git+https://github.com/fluencelabs/rust-sdk)",
|
||||
]
|
||||
@ -515,7 +560,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence-sdk-main"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#7018a64c29278a673e543867e691f74b3d652288"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#8418111074644a1bc197315060facd34778099de"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
@ -523,7 +568,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "fluence-sdk-wit"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#7018a64c29278a673e543867e691f74b3d652288"
|
||||
source = "git+https://github.com/fluencelabs/rust-sdk#8418111074644a1bc197315060facd34778099de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -715,7 +760,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"env_logger",
|
||||
"fluence-faas",
|
||||
"fluence-app-service",
|
||||
"log",
|
||||
]
|
||||
|
||||
@ -752,9 +797,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.73"
|
||||
version = "0.2.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
|
||||
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -836,6 +881,19 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "5.1.2"
|
||||
@ -1051,6 +1109,17 @@ version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.9"
|
||||
@ -1069,6 +1138,18 @@ version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
@ -1084,6 +1165,31 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustop"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccb57833f46c9d679d68f383e81b9a74b82aa8d6f8a9c9aaae7fc29476bc3274"
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3358c21cbbc1a751892528db4e1de4b7a2b6a73f001e215aaba97d712cfa9777"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-next",
|
||||
"libc",
|
||||
"log",
|
||||
"memchr",
|
||||
"nix 0.17.0",
|
||||
"scopeguard",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
"utf8parse",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
@ -1193,9 +1299,9 @@ checksum = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.36"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
|
||||
checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1341,6 +1447,12 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.1"
|
||||
@ -1434,7 +1546,7 @@ dependencies = [
|
||||
"cranelift-entity",
|
||||
"cranelift-native",
|
||||
"libc",
|
||||
"nix",
|
||||
"nix 0.15.0",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde-bench",
|
||||
@ -1503,7 +1615,7 @@ dependencies = [
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"nix",
|
||||
"nix 0.15.0",
|
||||
"page_size",
|
||||
"parking_lot",
|
||||
"rustc_version",
|
||||
@ -1532,7 +1644,7 @@ dependencies = [
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"nix",
|
||||
"nix 0.15.0",
|
||||
"page_size",
|
||||
"parking_lot",
|
||||
"rustc_version",
|
||||
|
@ -16,6 +16,7 @@ members = [
|
||||
"fluence-app-service",
|
||||
"fluence-faas",
|
||||
"tools/cli",
|
||||
"tools/repl",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
@ -67,16 +67,16 @@ impl FCE {
|
||||
/// Load a new module inside FCE.
|
||||
pub fn load_module<S: Into<String>>(
|
||||
&mut self,
|
||||
module_name: S,
|
||||
name: S,
|
||||
wasm_bytes: &[u8],
|
||||
config: FCEModuleConfig,
|
||||
) -> Result<()> {
|
||||
self.load_module_(module_name.into(), wasm_bytes, config)
|
||||
self.load_module_(name.into(), wasm_bytes, config)
|
||||
}
|
||||
|
||||
pub fn load_module_(
|
||||
&mut self,
|
||||
module_name: String,
|
||||
name: String,
|
||||
wasm_bytes: &[u8],
|
||||
config: FCEModuleConfig,
|
||||
) -> Result<()> {
|
||||
@ -84,7 +84,7 @@ impl FCE {
|
||||
|
||||
let module = FCEModule::new(&wasm_bytes, config, &self.modules)?;
|
||||
|
||||
match self.modules.entry(module_name) {
|
||||
match self.modules.entry(name) {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(module);
|
||||
Ok(())
|
||||
@ -94,8 +94,8 @@ impl FCE {
|
||||
}
|
||||
|
||||
/// Unload previously loaded module.
|
||||
pub fn unload_module<S: AsRef<str>>(&mut self, module_name: S) -> Result<()> {
|
||||
self.unload_module_(module_name.as_ref())
|
||||
pub fn unload_module<S: AsRef<str>>(&mut self, name: S) -> Result<()> {
|
||||
self.unload_module_(name.as_ref())
|
||||
}
|
||||
|
||||
pub fn unload_module_(&mut self, module_name: &str) -> Result<()> {
|
||||
|
@ -28,7 +28,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
greeting_node.get_interface()
|
||||
);
|
||||
|
||||
let result = greeting_node.call_module(
|
||||
let result = greeting_node.call(
|
||||
"greeting.wasm",
|
||||
"greeting",
|
||||
&[IValue::String("Fluence".to_string()), IValue::I32(1)],
|
||||
|
@ -5,7 +5,7 @@ authors = ["Fluence Labs"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
fluence-faas = { path = "../../fluence-faas" }
|
||||
fluence-app-service = { path = "../../fluence-app-service" }
|
||||
anyhow = "1.0.31"
|
||||
log = "0.4.11"
|
||||
env_logger = "0.7.1"
|
||||
|
@ -1,24 +1,18 @@
|
||||
core_modules_dir = "wasm/artifacts/wasm_modules"
|
||||
modules_dir = "wasm/artifacts/wasm_modules"
|
||||
service_base_dir = "/Users/tmp"
|
||||
|
||||
[[core_module]]
|
||||
[[module]]
|
||||
name = "ipfs_node.wasm"
|
||||
mem_pages_count = 100
|
||||
logger_enabled = true
|
||||
|
||||
[core_module.imports]
|
||||
mysql = "/usr/bin/mysql"
|
||||
[module.imports]
|
||||
ipfs = "/usr/local/bin/ipfs"
|
||||
|
||||
[core_module.wasi]
|
||||
[module.wasi]
|
||||
envs = ["IPFS_ADDR=/dns4/relay02.fluence.dev/tcp/15001", "timeout=1s"]
|
||||
preopened_files = ["./wasm/artifacts"]
|
||||
mapped_dirs = { "tmp" = "./wasm/artifacts" }
|
||||
|
||||
[rpc_module]
|
||||
[[module]]
|
||||
name = "zipfs_rpc.wasm"
|
||||
mem_pages_count = 100
|
||||
logger_enabled = true
|
||||
|
||||
[rpc_module.wasi]
|
||||
envs = []
|
||||
preopened_files = ["./wasm/artifacts"]
|
||||
mapped_dirs = { "tmp" = "./wasm/artifacts" }
|
||||
|
@ -14,27 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use fluence_faas::FluenceFaaS;
|
||||
use fluence_faas::IValue;
|
||||
use fluence_app_service::AppService;
|
||||
use fluence_app_service::IValue;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use anyhow::Context;
|
||||
|
||||
const IPFS_MODULES_CONFIG_PATH: &str = "Config.toml";
|
||||
const IPFS_RPC: &str = "wasm/artifacts/ipfs_rpc.wasm";
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
env_logger::init();
|
||||
let ipfs_rpc = std::fs::read(IPFS_RPC).with_context(|| format!("{} wasn't found", IPFS_RPC))?;
|
||||
|
||||
let mut ipfs_node = FluenceFaaS::new(PathBuf::from(IPFS_MODULES_CONFIG_PATH))?;
|
||||
let mut ipfs_node = AppService::with_raw_config();
|
||||
println!("ipfs node interface is\n{}", ipfs_node.get_interface());
|
||||
|
||||
let node_address = ipfs_node.call_module("ipfs_node.wasm", "get_address", &[])?;
|
||||
let node_address = ipfs_node.call("ipfs_node.wasm", "get_address", &[])?;
|
||||
println!("ipfs node address is:\n{:?}", node_address);
|
||||
|
||||
let result = ipfs_node.call_code(
|
||||
&ipfs_rpc,
|
||||
let result = ipfs_node.call(
|
||||
"ipfs_rpc.wasm",
|
||||
"get",
|
||||
&[IValue::String(
|
||||
"QmXdC36pX1B1sdHdbri859vMYctQjAhvTmkWyG9xzhShxb".to_string(),
|
||||
|
@ -26,7 +26,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
let mut records_test = FluenceFaaS::new(PathBuf::from(RECORDS_MODULES_CONFIG_PATH))?;
|
||||
println!("ipfs node interface is\n{}", records_test.get_interface());
|
||||
|
||||
let result = records_test.call_module("pure.wasm", "invoke", &[])?;
|
||||
let result = records_test.call("pure.wasm", "invoke", &[])?;
|
||||
println!("execution result {:?}", result);
|
||||
|
||||
Ok(())
|
||||
|
@ -7,14 +7,9 @@ edition = "2018"
|
||||
[dependencies]
|
||||
fluence-faas = { path = "../fluence-faas" }
|
||||
|
||||
wasmer-runtime = { package = "wasmer-runtime-fl", version = "0.17.0" }
|
||||
# dynamicfunc-fat-closures allows using state inside DynamicFunc
|
||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0", features = ["dynamicfunc-fat-closures"] }
|
||||
wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.0" }
|
||||
|
||||
toml = "0.5.6"
|
||||
serde = { version = "1.0.111", features = ["derive"] }
|
||||
serde_json = "1.0.53"
|
||||
serde_derive = "1.0.111"
|
||||
cmd_lib = "0.7.8"
|
||||
log = "0.4.8"
|
||||
|
||||
[features]
|
||||
raw-module-api = ["fluence-faas/raw-module-api"]
|
||||
|
@ -22,7 +22,7 @@ use std::error::Error;
|
||||
#[derive(Debug)]
|
||||
pub enum AppServiceError {
|
||||
/// An error related to config parsing.
|
||||
InvalidArguments(String),
|
||||
InvalidConfig(String),
|
||||
|
||||
/// Various errors related to file i/o.
|
||||
IOError(String),
|
||||
@ -36,7 +36,7 @@ impl Error for AppServiceError {}
|
||||
impl std::fmt::Display for AppServiceError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
AppServiceError::InvalidArguments(err_msg) => write!(f, "{}", err_msg),
|
||||
AppServiceError::InvalidConfig(err_msg) => write!(f, "{}", err_msg),
|
||||
AppServiceError::IOError(err_msg) => write!(f, "{}", err_msg),
|
||||
AppServiceError::FaaSError(err) => write!(f, "{}", err),
|
||||
}
|
||||
@ -57,12 +57,12 @@ impl From<FaaSError> for AppServiceError {
|
||||
|
||||
impl From<toml::de::Error> for AppServiceError {
|
||||
fn from(err: toml::de::Error) -> Self {
|
||||
AppServiceError::InvalidArguments(format!("{}", err))
|
||||
AppServiceError::InvalidConfig(format!("{}", err))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::convert::Infallible> for AppServiceError {
|
||||
fn from(inf: std::convert::Infallible) -> Self {
|
||||
match inf {}
|
||||
fn from(_: std::convert::Infallible) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use fluence_faas::FluenceFaaS;
|
||||
use fluence_faas::ModulesConfig;
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const SERVICE_ID_ENV_NAME: &str = "service_id";
|
||||
const SERVICE_LOCAL_DIR_NAME: &str = "local";
|
||||
@ -35,7 +36,7 @@ pub struct AppService {
|
||||
}
|
||||
|
||||
impl AppService {
|
||||
/// Creates Service with given modules and service id.
|
||||
/// Create Service with given modules and service id.
|
||||
pub fn new<I, C, S>(modules: I, config: C, service_id: S) -> Result<Self>
|
||||
where
|
||||
I: IntoIterator<Item = String>,
|
||||
@ -45,7 +46,7 @@ impl AppService {
|
||||
{
|
||||
let config: ModulesConfig = config.try_into()?;
|
||||
let service_id = service_id.as_ref();
|
||||
let config = Self::set_env_and_dirs(config, service_id)?;
|
||||
let config = Self::set_env_and_dirs(config, service_id, None)?;
|
||||
|
||||
let modules = modules.into_iter().collect();
|
||||
let faas = FluenceFaaS::with_module_names(&modules, config)?;
|
||||
@ -53,9 +54,33 @@ impl AppService {
|
||||
Ok(Self { faas })
|
||||
}
|
||||
|
||||
/// Create Service with given raw config, service id and service base dir.
|
||||
pub fn with_raw_config<P, SI>(
|
||||
config: P,
|
||||
service_id: SI,
|
||||
service_base_dir: Option<&str>,
|
||||
) -> Result<Self>
|
||||
where
|
||||
P: Into<PathBuf>,
|
||||
SI: AsRef<str>,
|
||||
{
|
||||
let service_id = service_id.as_ref();
|
||||
let service_base_dir = service_base_dir;
|
||||
|
||||
let config_content = std::fs::read(config.into())?;
|
||||
let config: crate::RawModulesConfig = toml::from_slice(&config_content)?;
|
||||
|
||||
let config = config.try_into()?;
|
||||
let config = Self::set_env_and_dirs(config, service_id, service_base_dir)?;
|
||||
|
||||
let faas = FluenceFaaS::with_raw_config(config)?;
|
||||
|
||||
Ok(Self { faas })
|
||||
}
|
||||
|
||||
/// Call a specified function of loaded module by its name.
|
||||
// TODO: replace serde_json::Value with Vec<u8>?
|
||||
pub fn call_module<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
pub fn call<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
&mut self,
|
||||
module_name: MN,
|
||||
func_name: FN,
|
||||
@ -64,7 +89,7 @@ impl AppService {
|
||||
let arguments = Self::json_to_ivalue(arguments)?;
|
||||
|
||||
self.faas
|
||||
.call_module(module_name, func_name, &arguments)
|
||||
.call(module_name, func_name, &arguments)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
@ -78,11 +103,15 @@ impl AppService {
|
||||
/// - service_base_dir/service_id/SERVICE_LOCAL_DIR_NAME
|
||||
/// - service_base_dir/service_id/SERVICE_TMP_DIR_NAME
|
||||
/// 2. adding service_id to environment variables
|
||||
fn set_env_and_dirs(mut config: ModulesConfig, service_id: &str) -> Result<ModulesConfig> {
|
||||
let base_dir = match config.service_base_dir {
|
||||
Some(ref base_dir) => base_dir,
|
||||
// TODO: refactor it later
|
||||
None => {
|
||||
fn set_env_and_dirs(
|
||||
mut config: ModulesConfig,
|
||||
service_id: &str,
|
||||
service_base_dir: Option<&str>,
|
||||
) -> Result<ModulesConfig> {
|
||||
let base_dir = match (&config.service_base_dir, service_base_dir) {
|
||||
(_, Some(base_dir)) => base_dir,
|
||||
(Some(ref base_dir), None) => base_dir,
|
||||
_ => {
|
||||
return Err(AppServiceError::IOError(String::from(
|
||||
"service_base_dir should be specified",
|
||||
)))
|
||||
@ -130,7 +159,7 @@ impl AppService {
|
||||
let is_empty_obj = arguments.as_object().map_or(false, |m| m.is_empty());
|
||||
let arguments = if !is_null && !is_empty_arr && !is_empty_obj {
|
||||
Some(fluence_faas::to_interface_value(&arguments).map_err(|e| {
|
||||
AppServiceError::InvalidArguments(format!(
|
||||
AppServiceError::InvalidConfig(format!(
|
||||
"can't parse arguments as array of interface types: {}",
|
||||
e
|
||||
))
|
||||
@ -143,10 +172,29 @@ impl AppService {
|
||||
Some(IValue::Record(arguments)) => Ok(arguments.into_vec()),
|
||||
// Convert null, [] and {} into vec![]
|
||||
None => Ok(vec![]),
|
||||
other => Err(AppServiceError::InvalidArguments(format!(
|
||||
other => Err(AppServiceError::InvalidConfig(format!(
|
||||
"expected array of interface values: got {:?}",
|
||||
other
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This API is intended for testing purposes (mostly in FCE REPL)
|
||||
#[cfg(feature = "raw-module-api")]
|
||||
impl AppService {
|
||||
pub fn load_module<S, C>(&mut self, name: S, wasm_bytes: &[u8], config: Option<C>) -> Result<()>
|
||||
where
|
||||
S: Into<String>,
|
||||
C: TryInto<crate::ModuleConfig>,
|
||||
fluence_faas::FaaSError: From<C::Error>,
|
||||
{
|
||||
self.faas
|
||||
.load_module(name, &wasm_bytes, config)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn unload_module<S: AsRef<str>>(&mut self, module_name: S) -> Result<()> {
|
||||
self.faas.unload_module(module_name).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
@ -18,3 +18,6 @@ serde_json = "1.0.53"
|
||||
serde_derive = "1.0.111"
|
||||
cmd_lib = "0.7.8"
|
||||
log = "0.4.8"
|
||||
|
||||
[features]
|
||||
raw-module-api = []
|
||||
|
@ -62,7 +62,7 @@ impl From<toml::de::Error> for FaaSError {
|
||||
}
|
||||
|
||||
impl From<std::convert::Infallible> for FaaSError {
|
||||
fn from(inf: std::convert::Infallible) -> Self {
|
||||
match inf {}
|
||||
fn from(_: std::convert::Infallible) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
@ -15,19 +15,18 @@
|
||||
*/
|
||||
|
||||
use crate::misc::ModulesConfig;
|
||||
use crate::faas_interface::FaaSFunctionSignature;
|
||||
use crate::faas_interface::FaaSInterface;
|
||||
use crate::FaaSError;
|
||||
use crate::Result;
|
||||
|
||||
use super::faas_interface::FaaSInterface;
|
||||
use super::FaaSError;
|
||||
use super::IValue;
|
||||
use crate::IValue;
|
||||
|
||||
use fce::FCE;
|
||||
|
||||
use std::convert::TryInto;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use crate::faas_interface::FaaSFunctionSignature;
|
||||
use std::collections::HashSet;
|
||||
|
||||
// TODO: remove and use mutex instead
|
||||
unsafe impl Send for FluenceFaaS {}
|
||||
@ -86,13 +85,15 @@ impl FluenceFaaS {
|
||||
/// Creates FaaS from config deserialized from TOML.
|
||||
pub fn with_raw_config<C>(config: C) -> Result<Self>
|
||||
where
|
||||
C: TryInto<ModulesConfig, Error = FaaSError>,
|
||||
C: TryInto<ModulesConfig>,
|
||||
FaaSError: From<C::Error>,
|
||||
{
|
||||
let config = config.try_into()?;
|
||||
let modules = config.modules_dir.as_ref().map_or(Ok(vec![]), |dir| {
|
||||
Self::load_modules(dir, ModulesLoadStrategy::All)
|
||||
})?;
|
||||
Self::with_modules(modules, config)
|
||||
|
||||
Self::with_modules::<_, ModulesConfig>(modules, config)
|
||||
}
|
||||
|
||||
/// Creates FaaS with given modules.
|
||||
@ -110,7 +111,6 @@ impl FluenceFaaS {
|
||||
module_config @ Some(_) => module_config,
|
||||
None => config.default_modules_config.clone(),
|
||||
};
|
||||
|
||||
let fce_module_config = crate::misc::make_fce_config(module_config)?;
|
||||
fce.load_module(name.clone(), &bytes, fce_module_config)?;
|
||||
}
|
||||
@ -178,7 +178,7 @@ impl FluenceFaaS {
|
||||
}
|
||||
|
||||
/// Call a specified function of loaded on a startup module by its name.
|
||||
pub fn call_module<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
pub fn call<MN: AsRef<str>, FN: AsRef<str>>(
|
||||
&mut self,
|
||||
module_name: MN,
|
||||
func_name: FN,
|
||||
@ -214,3 +214,25 @@ impl FluenceFaaS {
|
||||
FaaSInterface { modules }
|
||||
}
|
||||
}
|
||||
|
||||
// This API is intended for testing purposes (mostly in FCE REPL)
|
||||
#[cfg(feature = "raw-module-api")]
|
||||
impl FluenceFaaS {
|
||||
pub fn load_module<S, C>(&mut self, name: S, wasm_bytes: &[u8], config: Option<C>) -> Result<()>
|
||||
where
|
||||
S: Into<String>,
|
||||
C: TryInto<crate::ModuleConfig>,
|
||||
FaaSError: From<C::Error>,
|
||||
{
|
||||
let config = config.map(|c| c.try_into()).transpose()?;
|
||||
|
||||
let fce_module_config = crate::misc::make_fce_config(config)?;
|
||||
self.fce
|
||||
.load_module(name, &wasm_bytes, fce_module_config)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub fn unload_module<S: AsRef<str>>(&mut self, module_name: S) -> Result<()> {
|
||||
self.fce.unload_module(module_name).map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ use crate::FaaSError;
|
||||
use crate::Result;
|
||||
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
use toml::from_slice;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
@ -70,7 +69,7 @@ impl TryInto<ModulesConfig> for RawModulesConfig {
|
||||
type Error = FaaSError;
|
||||
|
||||
fn try_into(self) -> Result<ModulesConfig> {
|
||||
from_raw_config(self)
|
||||
from_raw_modules_config(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +82,14 @@ pub struct RawModuleConfig {
|
||||
pub wasi: Option<RawWASIConfig>,
|
||||
}
|
||||
|
||||
impl TryInto<ModuleConfig> for RawModuleConfig {
|
||||
type Error = FaaSError;
|
||||
|
||||
fn try_into(self) -> Result<ModuleConfig> {
|
||||
from_raw_module_config(self).map(|(_, module_config)| module_config)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
|
||||
pub struct RawDefaultModuleConfig {
|
||||
pub mem_pages_count: Option<u32>,
|
||||
@ -209,7 +216,7 @@ pub struct WASIConfig {
|
||||
}
|
||||
|
||||
/// Prepare config after parsing it from TOML.
|
||||
fn from_raw_config(config: RawModulesConfig) -> Result<ModulesConfig> {
|
||||
fn from_raw_modules_config(config: RawModulesConfig) -> Result<ModulesConfig> {
|
||||
let service_base_dir = config.service_base_dir;
|
||||
let modules_config = config
|
||||
.module
|
||||
@ -233,7 +240,7 @@ fn from_raw_config(config: RawModulesConfig) -> Result<ModulesConfig> {
|
||||
/// Parse config from TOML.
|
||||
pub(crate) fn load_config(config_file_path: std::path::PathBuf) -> Result<RawModulesConfig> {
|
||||
let file_content = std::fs::read(config_file_path)?;
|
||||
Ok(from_slice(&file_content)?)
|
||||
Ok(toml::from_slice(&file_content)?)
|
||||
}
|
||||
|
||||
fn from_raw_module_config(config: RawModuleConfig) -> Result<(String, ModuleConfig)> {
|
||||
|
23
tools/repl/Cargo.toml
Normal file
23
tools/repl/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "fce-repl"
|
||||
description = "Fluence FCE REPL intended for testing purposes"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
repository = "https://github.com/fluencelabs/fce/tools/repl"
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "fce-repl"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
fluence-app-service = { path = "../../fluence-app-service", features = ["raw-module-api"] }
|
||||
|
||||
anyhow = "1.0.31"
|
||||
clap = "2.33.1"
|
||||
serde_json = "1.0.57"
|
||||
|
||||
rustyline = "6.1.2"
|
||||
rustop = "1.1.0"
|
||||
uuid = { version = "0.8.1", features = ["v4"] }
|
174
tools/repl/src/main.rs
Normal file
174
tools/repl/src/main.rs
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#![deny(
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
/// Command-line tool intended to test Fluence FaaS.
|
||||
use std::fs;
|
||||
|
||||
macro_rules! next_argument {
|
||||
($arg_name:ident, $args:ident, $error_msg:expr) => {
|
||||
let $arg_name = if let Some($arg_name) = $args.next() {
|
||||
$arg_name
|
||||
} else {
|
||||
println!($error_msg);
|
||||
continue;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
let (args, _) = rustop::opts! {
|
||||
synopsis "Fluence Application service REPL";
|
||||
param config_file_path: Option<String>, desc: "Path to a service config";
|
||||
}
|
||||
.parse_or_exit();
|
||||
|
||||
println!("Welcome to the Fluence FaaS REPL:");
|
||||
let mut app_service = create_service_from_config(args.config_file_path)?;
|
||||
|
||||
let mut rl = rustyline::Editor::<()>::new();
|
||||
loop {
|
||||
let readline = rl.readline(">> ");
|
||||
let readline = match readline {
|
||||
Ok(readline) => readline,
|
||||
Err(e) => {
|
||||
println!("a error occurred: {}", e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let mut args = readline.split_whitespace();
|
||||
match args.next() {
|
||||
Some("new") => {
|
||||
app_service = match create_service_from_config(args.next()) {
|
||||
Ok(service) => service,
|
||||
Err(e) => {
|
||||
println!("failed to create a new application service: {}", e);
|
||||
app_service
|
||||
}
|
||||
};
|
||||
}
|
||||
Some("load") => {
|
||||
next_argument!(module_name, args, "Module name should be specified");
|
||||
next_argument!(module_path, args, "Module path should be specified");
|
||||
|
||||
let wasm_bytes = fs::read(module_path);
|
||||
if let Err(e) = wasm_bytes {
|
||||
println!("failed to read wasm module: {}", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
let result_msg = match app_service
|
||||
.load_module::<String, fluence_app_service::ModuleConfig>(
|
||||
module_name.into(),
|
||||
&wasm_bytes.unwrap(),
|
||||
None,
|
||||
) {
|
||||
Ok(_) => "module successfully loaded into App service".to_string(),
|
||||
Err(e) => format!("module loaded failed with: {:?}", e),
|
||||
};
|
||||
println!("{}", result_msg);
|
||||
}
|
||||
Some("unload") => {
|
||||
next_argument!(module_name, args, "Module name should be specified");
|
||||
|
||||
let result_msg = match app_service.unload_module(module_name) {
|
||||
Ok(_) => "module successfully unloaded from App service".to_string(),
|
||||
Err(e) => format!("module unloaded failed with: {:?}", e),
|
||||
};
|
||||
println!("{}", result_msg);
|
||||
}
|
||||
Some("call") => {
|
||||
next_argument!(module_name, args, "Module name should be specified");
|
||||
next_argument!(func_name, args, "Function name should be specified");
|
||||
|
||||
let module_arg: String = args.collect();
|
||||
let module_arg: serde_json::Value = match serde_json::from_str(&module_arg) {
|
||||
Ok(module_arg) => module_arg,
|
||||
Err(e) => {
|
||||
println!("incorrect arguments {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let result = match app_service.call(module_name, func_name, module_arg) {
|
||||
Ok(result) => format!("result: {:?}", result),
|
||||
Err(e) => format!("execution failed with {:?}", e),
|
||||
};
|
||||
println!("{}", result);
|
||||
}
|
||||
Some("interface") => {
|
||||
let interface = app_service.get_interface();
|
||||
println!("application service interface: {}", interface);
|
||||
}
|
||||
Some("h") | Some("help") | None => {
|
||||
println!(
|
||||
"Enter:\n\
|
||||
new [config_path] - to create a new AppService (old will be removed)
|
||||
load <module_name> <module_path> - to load a new Wasm module into App service\n\
|
||||
unload <module_name> - to unload Wasm module from AppService\n\
|
||||
call <module_name> <func_name> [args] - to call function with given name on module with given module_name\n\
|
||||
interface - to print public interface of current AppService\n\
|
||||
h/help - to print this message\n\
|
||||
e/exit/q/quit - to exit"
|
||||
);
|
||||
}
|
||||
Some("e") | Some("exit") | Some("q") | Some("quit") => break,
|
||||
_ => {
|
||||
println!("unsupported command");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_service_from_config<S: Into<String>>(
|
||||
config_file_path: Option<S>,
|
||||
) -> Result<fluence_app_service::AppService, anyhow::Error> {
|
||||
let tmp_path: String = std::env::temp_dir().to_string_lossy().into();
|
||||
let service_id = uuid::Uuid::new_v4().to_string();
|
||||
|
||||
let app_service = match config_file_path {
|
||||
Some(config_file_path) => {
|
||||
let config_file_path = config_file_path.into();
|
||||
fluence_app_service::AppService::with_raw_config(
|
||||
config_file_path,
|
||||
&service_id,
|
||||
Some(&tmp_path),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
let mut config: fluence_app_service::RawModulesConfig = <_>::default();
|
||||
config.service_base_dir = Some(tmp_path);
|
||||
|
||||
fluence_app_service::AppService::new(std::iter::empty(), config, &service_id)
|
||||
}
|
||||
}?;
|
||||
|
||||
println!("app service's created with service id = {}", service_id);
|
||||
|
||||
Ok(app_service)
|
||||
}
|
Loading…
Reference in New Issue
Block a user