marine/config/
raw_marine_config.rs

1/*
2 * Copyright 2020 Fluence Labs Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::MarineError;
18use crate::MarineResult;
19
20use bytesize::ByteSize;
21use serde_derive::Serialize;
22use serde_derive::Deserialize;
23use serde_with::serde_as;
24use serde_with::skip_serializing_none;
25
26use std::path::Path;
27use std::path::PathBuf;
28
29/*
30An example of the config:
31
32modules_dir = "wasm/artifacts/wasm_modules"
33
34[[module]]
35    name = "ipfs_node.wasm"
36    mem_pages_count = 100
37    logger_enabled = true
38
39    [module.mounted_binaries]
40    mysql = "/usr/bin/mysql"
41    ipfs = "/usr/local/bin/ipfs"
42
43    [module.wasi]
44    envs = { "IPFS_ADDR" = "/dns4/relay02.fluence.dev/tcp/15001" }
45    mapped_dirs = {"tmp" = "/Users/user/tmp"}
46
47[default]
48    mem_pages_count = 100
49    logger_enabled = true
50
51    [default.mounted_binaries]
52    mysql = "/usr/bin/mysql"
53    ipfs = "/usr/local/bin/ipfs"
54
55    [default.wasi]
56    envs = []
57    mapped_dirs = {"tmp" = "/Users/user/tmp"}
58 */
59
60#[derive(Deserialize, Serialize, Debug, Clone, Default)]
61pub struct TomlMarineConfig {
62    pub modules_dir: Option<PathBuf>,
63    pub total_memory_limit: MemoryLimit,
64    #[serde(skip_serializing_if = "Vec::is_empty")]
65    pub module: Vec<TomlMarineNamedModuleConfig>,
66    pub default: Option<TomlMarineModuleConfig>,
67    #[serde(skip)]
68    pub base_path: PathBuf,
69}
70
71impl TomlMarineConfig {
72    /// Load config from filesystem.
73    pub fn load<P: AsRef<Path>>(path: P) -> MarineResult<Self> {
74        let path = PathBuf::from(path.as_ref()).canonicalize().map_err(|e| {
75            MarineError::IOError(format!(
76                "failed to canonicalize path {}: {}",
77                path.as_ref().display(),
78                e
79            ))
80        })?;
81
82        let file_content = std::fs::read(&path).map_err(|e| {
83            MarineError::IOError(format!("failed to load {}: {}", path.display(), e))
84        })?;
85
86        let mut config: TomlMarineConfig = toml::from_slice(&file_content)?;
87
88        let default_base_path = Path::new("/");
89        config.base_path = path
90            .canonicalize()
91            .map_err(|e| {
92                MarineError::IOError(format!(
93                    "Failed to canonicalize config path {}: {}",
94                    path.display(),
95                    e
96                ))
97            })?
98            .parent()
99            .unwrap_or(default_base_path)
100            .to_path_buf();
101
102        Ok(config)
103    }
104}
105
106#[derive(Deserialize, Serialize, Debug, Clone, Default)]
107pub struct TomlMarineNamedModuleConfig {
108    pub name: String,
109    #[serde(default)]
110    pub load_from: Option<PathBuf>,
111    #[serde(default)]
112    pub file_name: Option<String>,
113    #[serde(flatten)]
114    pub config: TomlMarineModuleConfig,
115}
116
117#[skip_serializing_none]
118#[derive(Deserialize, Serialize, Debug, Clone, Default)]
119pub struct TomlMarineModuleConfig {
120    pub logger_enabled: Option<bool>,
121    pub logging_mask: Option<i32>,
122    pub wasi: Option<TomlWASIConfig>,
123    pub mounted_binaries: Option<toml::value::Table>,
124}
125
126#[derive(Deserialize, Serialize, Debug, Clone, Default)]
127pub struct TomlWASIConfig {
128    pub envs: Option<toml::value::Table>,
129    pub mapped_dirs: Option<toml::value::Table>,
130}
131
132#[derive(Serialize, Deserialize, Debug, Clone, Default)]
133#[serde_as]
134pub enum MemoryLimit {
135    #[default]
136    #[serde(alias = "infinity")]
137    Infinity,
138    #[serde(untagged)]
139    Value(#[serde_as(as = "Option<DisplayFromStr>")] ByteSize),
140}
141
142#[cfg(test)]
143mod tests {
144    use super::TomlMarineNamedModuleConfig;
145    use super::TomlMarineModuleConfig;
146    use super::TomlWASIConfig;
147
148    #[test]
149    fn serialize_marine_named_module_config() {
150        let mut mounted_binaries = toml::value::Table::new();
151        mounted_binaries.insert(
152            "curl".to_string(),
153            toml::Value::String("/usr/local/bin/curl".to_string()),
154        );
155
156        let config = TomlMarineNamedModuleConfig {
157            name: "name".to_string(),
158            file_name: Some("file_name".to_string()),
159            load_from: <_>::default(),
160            config: TomlMarineModuleConfig {
161                logger_enabled: Some(false),
162                logging_mask: Some(1),
163                wasi: Some(TomlWASIConfig {
164                    envs: None,
165                    mapped_dirs: None,
166                }),
167                mounted_binaries: Some(mounted_binaries),
168            },
169        };
170
171        assert!(toml::to_string(&config).is_ok())
172    }
173}