mirror of
https://github.com/fluencelabs/marine.git
synced 2024-12-12 14:55:32 +00:00
255 lines
7.2 KiB
Rust
255 lines
7.2 KiB
Rust
/*
|
|
* 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.
|
|
*/
|
|
|
|
use crate::FaaSError;
|
|
use crate::Result;
|
|
use crate::config::*;
|
|
|
|
use serde_derive::Serialize;
|
|
use serde_derive::Deserialize;
|
|
|
|
use std::convert::TryInto;
|
|
use std::collections::HashMap;
|
|
use std::collections::HashSet;
|
|
use std::path::PathBuf;
|
|
|
|
/*
|
|
An example of the config:
|
|
|
|
modules_dir = "wasm/artifacts/wasm_modules"
|
|
|
|
[[module]]
|
|
name = "ipfs_node.wasm"
|
|
mem_pages_count = 100
|
|
logger_enabled = true
|
|
|
|
[module.mounted_binaries]
|
|
mysql = "/usr/bin/mysql"
|
|
ipfs = "/usr/local/bin/ipfs"
|
|
|
|
[module.wasi]
|
|
envs = { "IPFS_ADDR" = "/dns4/relay02.fluence.dev/tcp/15001" }
|
|
preopened_files = ["/Users/user/tmp"]
|
|
mapped_dirs = {"tmp" = "/Users/user/tmp"}
|
|
|
|
[default]
|
|
mem_pages_count = 100
|
|
logger_enabled = true
|
|
|
|
[default.mounted_binaries]
|
|
mysql = "/usr/bin/mysql"
|
|
ipfs = "/usr/local/bin/ipfs"
|
|
|
|
[default.wasi]
|
|
envs = []
|
|
preopened_files = ["/Users/user/tmp"]
|
|
mapped_dirs = {"tmp" = "/Users/user/tmp"}
|
|
*/
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
|
|
pub struct TomlFaaSConfig {
|
|
pub modules_dir: Option<String>,
|
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
|
pub module: Vec<TomlFaaSNamedModuleConfig>,
|
|
pub default: Option<TomlFaaSModuleConfig>,
|
|
}
|
|
|
|
impl TomlFaaSConfig {
|
|
/// Load config from filesystem.
|
|
pub fn load<P: Into<PathBuf>>(path: P) -> Result<Self> {
|
|
let path = path.into();
|
|
let file_content = std::fs::read(&path)?;
|
|
toml::from_slice(&file_content).map_err(|e| {
|
|
FaaSError::ConfigParseError(format!("Error parsing config {:?}: {:?}", path, e))
|
|
})
|
|
}
|
|
}
|
|
|
|
impl TryInto<FaaSConfig> for TomlFaaSConfig {
|
|
type Error = FaaSError;
|
|
|
|
fn try_into(self) -> Result<FaaSConfig> {
|
|
from_toml_faas_config(self)
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
|
|
pub struct TomlFaaSNamedModuleConfig {
|
|
pub name: String,
|
|
#[serde(flatten)]
|
|
pub config: TomlFaaSModuleConfig,
|
|
}
|
|
|
|
impl TryInto<(String, FaaSModuleConfig)> for TomlFaaSNamedModuleConfig {
|
|
type Error = FaaSError;
|
|
|
|
fn try_into(self) -> Result<(String, FaaSModuleConfig)> {
|
|
from_toml_named_module_config(self)
|
|
}
|
|
}
|
|
|
|
impl TryInto<FaaSModuleConfig> for TomlFaaSNamedModuleConfig {
|
|
type Error = FaaSError;
|
|
|
|
fn try_into(self) -> Result<FaaSModuleConfig> {
|
|
from_toml_named_module_config(self).map(|(_, module_config)| module_config)
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
|
|
pub struct TomlFaaSModuleConfig {
|
|
pub mem_pages_count: Option<u32>,
|
|
pub logger_enabled: Option<bool>,
|
|
pub wasi: Option<TomlWASIConfig>,
|
|
pub mounted_binaries: Option<toml::value::Table>,
|
|
pub logging_mask: Option<i64>,
|
|
}
|
|
|
|
impl TomlFaaSNamedModuleConfig {
|
|
pub fn new<S>(name: S) -> Self
|
|
where
|
|
S: Into<String>,
|
|
{
|
|
Self {
|
|
name: name.into(),
|
|
config: <_>::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
|
|
pub struct TomlWASIConfig {
|
|
pub preopened_files: Option<Vec<String>>,
|
|
pub envs: Option<toml::value::Table>,
|
|
pub mapped_dirs: Option<toml::value::Table>,
|
|
}
|
|
|
|
/// Prepare config after parsing it from TOML.
|
|
pub fn from_toml_faas_config(config: TomlFaaSConfig) -> Result<FaaSConfig> {
|
|
let modules_config = config
|
|
.module
|
|
.into_iter()
|
|
.map(from_toml_named_module_config)
|
|
.collect::<Result<Vec<_>>>()?;
|
|
|
|
let default_modules_config = config.default.map(from_toml_module_config).transpose()?;
|
|
|
|
Ok(FaaSConfig {
|
|
modules_dir: config.modules_dir.map(PathBuf::from),
|
|
modules_config,
|
|
default_modules_config,
|
|
})
|
|
}
|
|
|
|
pub fn from_toml_named_module_config(
|
|
config: TomlFaaSNamedModuleConfig,
|
|
) -> Result<(String, FaaSModuleConfig)> {
|
|
let module_config = from_toml_module_config(config.config)?;
|
|
Ok((config.name, module_config))
|
|
}
|
|
|
|
pub fn from_toml_module_config(config: TomlFaaSModuleConfig) -> Result<FaaSModuleConfig> {
|
|
let mounted_binaries = config.mounted_binaries.unwrap_or_default();
|
|
let mounted_binaries = mounted_binaries
|
|
.into_iter()
|
|
.map(|(import_func_name, host_cmd)| {
|
|
let host_cmd = host_cmd.try_into::<String>()?;
|
|
Ok((import_func_name, host_cmd))
|
|
})
|
|
.collect::<Result<Vec<_>>>()?;
|
|
|
|
let mut host_cli_imports = HashMap::new();
|
|
for (import_name, host_cmd) in mounted_binaries {
|
|
host_cli_imports.insert(import_name, crate::misc::create_host_import(host_cmd));
|
|
}
|
|
|
|
let wasi = config.wasi.map(from_toml_wasi_config).transpose()?;
|
|
Ok(FaaSModuleConfig {
|
|
mem_pages_count: config.mem_pages_count,
|
|
logger_enabled: config.logger_enabled.unwrap_or(true),
|
|
host_imports: host_cli_imports,
|
|
wasi,
|
|
logging_mask: config.logging_mask.unwrap_or(i64::max_value()),
|
|
})
|
|
}
|
|
|
|
pub fn from_toml_wasi_config(wasi: TomlWASIConfig) -> Result<FaaSWASIConfig> {
|
|
let to_vec = |elem: (String, toml::Value)| -> Result<(Vec<u8>, Vec<u8>)> {
|
|
let to = elem
|
|
.1
|
|
.try_into::<String>()
|
|
.map_err(FaaSError::ParseConfigError)?;
|
|
Ok((elem.0.into_bytes(), to.into_bytes()))
|
|
};
|
|
|
|
let to_path = |elem: (String, toml::Value)| -> Result<(String, PathBuf)> {
|
|
let to = elem
|
|
.1
|
|
.try_into::<String>()
|
|
.map_err(FaaSError::ParseConfigError)?;
|
|
Ok((elem.0, PathBuf::from(to)))
|
|
};
|
|
|
|
let envs = wasi.envs.unwrap_or_default();
|
|
let envs = envs
|
|
.into_iter()
|
|
.map(to_vec)
|
|
.collect::<Result<HashMap<_, _>>>()?;
|
|
|
|
let preopened_files = wasi.preopened_files.unwrap_or_default();
|
|
let preopened_files = preopened_files
|
|
.into_iter()
|
|
.map(PathBuf::from)
|
|
.collect::<HashSet<_>>();
|
|
|
|
let mapped_dirs = wasi.mapped_dirs.unwrap_or_default();
|
|
let mapped_dirs = mapped_dirs
|
|
.into_iter()
|
|
.map(to_path)
|
|
.collect::<Result<HashMap<_, _>>>()?;
|
|
|
|
Ok(FaaSWASIConfig {
|
|
envs,
|
|
preopened_files,
|
|
mapped_dirs,
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::{TomlFaaSNamedModuleConfig, TomlFaaSModuleConfig, TomlWASIConfig};
|
|
|
|
#[test]
|
|
fn serialize_named() {
|
|
let config = TomlFaaSNamedModuleConfig {
|
|
name: "name".to_string(),
|
|
config: TomlFaaSModuleConfig {
|
|
mem_pages_count: Some(100),
|
|
logger_enabled: Some(false),
|
|
wasi: Some(TomlWASIConfig {
|
|
preopened_files: Some(vec!["a".to_string()]),
|
|
envs: None,
|
|
mapped_dirs: None,
|
|
}),
|
|
mounted_binaries: None,
|
|
logging_mask: None,
|
|
},
|
|
};
|
|
|
|
assert!(toml::to_string(&config).is_ok())
|
|
}
|
|
}
|