wash_cli/
config.rs

1use std::collections::HashMap;
2
3use anyhow::{anyhow, Result};
4
5use crate::cmd::up::WasmcloudOpts;
6use crate::creds::parse_credsfile;
7
8// NATS configuration values
9pub const NATS_SERVER_VERSION: &str = "v2.10.20";
10pub const DEFAULT_NATS_HOST: &str = "127.0.0.1";
11pub const DEFAULT_NATS_PORT: &str = "4222";
12pub const DEFAULT_NATS_WEBSOCKET_PORT: &str = "4223";
13
14// wadm configuration values
15pub const WADM_VERSION: &str = "v0.20.2";
16
17// wasmCloud configuration values, https://wasmcloud.com/docs/reference/host-config
18pub const WASMCLOUD_HOST_VERSION: &str = "v1.6.1";
19
20// NATS isolation configuration variables
21pub const WASMCLOUD_LATTICE: &str = "WASMCLOUD_LATTICE";
22pub const DEFAULT_LATTICE: &str = "default";
23pub const WASMCLOUD_JS_DOMAIN: &str = "WASMCLOUD_JS_DOMAIN";
24pub const WASMCLOUD_POLICY_TOPIC: &str = "WASMCLOUD_POLICY_TOPIC";
25pub const WASMCLOUD_SECRETS_TOPIC: &str = "WASMCLOUD_SECRETS_TOPIC";
26
27// Host / Cluster configuration
28pub const WASMCLOUD_CLUSTER_ISSUERS: &str = "WASMCLOUD_CLUSTER_ISSUERS";
29pub const WASMCLOUD_CLUSTER_SEED: &str = "WASMCLOUD_CLUSTER_SEED";
30pub const WASMCLOUD_HOST_SEED: &str = "WASMCLOUD_HOST_SEED";
31pub const WASMCLOUD_MAX_EXECUTION_TIME_MS: &str = "WASMCLOUD_MAX_EXECUTION_TIME_MS";
32pub const DEFAULT_MAX_EXECUTION_TIME_MS: &str = "600000";
33
34// NATS RPC connection configuration
35pub const WASMCLOUD_RPC_HOST: &str = "WASMCLOUD_RPC_HOST";
36pub const WASMCLOUD_RPC_PORT: &str = "WASMCLOUD_RPC_PORT";
37pub const WASMCLOUD_RPC_TIMEOUT_MS: &str = "WASMCLOUD_RPC_TIMEOUT_MS";
38pub const DEFAULT_RPC_TIMEOUT_MS: &str = "2000";
39pub const WASMCLOUD_RPC_JWT: &str = "WASMCLOUD_RPC_JWT";
40pub const WASMCLOUD_RPC_SEED: &str = "WASMCLOUD_RPC_SEED";
41pub const WASMCLOUD_RPC_CREDSFILE: &str = "WASMCLOUD_RPC_CREDSFILE";
42pub const WASMCLOUD_RPC_TLS: &str = "WASMCLOUD_RPC_TLS";
43pub const WASMCLOUD_RPC_TLS_FIRST: &str = "WASMCLOUD_RPC_TLS_FIRST";
44pub const WASMCLOUD_RPC_TLS_CA_FILE: &str = "WASMCLOUD_RPC_TLS_CA_FILE";
45
46// NATS CTL connection configuration
47pub const WASMCLOUD_CTL_HOST: &str = "WASMCLOUD_CTL_HOST";
48pub const WASMCLOUD_CTL_PORT: &str = "WASMCLOUD_CTL_PORT";
49pub const WASMCLOUD_CTL_SEED: &str = "WASMCLOUD_CTL_SEED";
50pub const WASMCLOUD_CTL_JWT: &str = "WASMCLOUD_CTL_JWT";
51pub const WASMCLOUD_CTL_CREDSFILE: &str = "WASMCLOUD_CTL_CREDSFILE";
52pub const WASMCLOUD_CTL_TLS: &str = "WASMCLOUD_CTL_TLS";
53pub const WASMCLOUD_CTL_TLS_FIRST: &str = "WASMCLOUD_CTL_TLS_FIRST";
54pub const WASMCLOUD_CTL_TLS_CA_FILE: &str = "WASMCLOUD_CTL_TLS_CA_FILE";
55
56// NATS Provider RPC connection configuration
57pub const WASMCLOUD_PROV_SHUTDOWN_DELAY_MS: &str = "WASMCLOUD_PROV_SHUTDOWN_DELAY_MS";
58pub const DEFAULT_PROV_SHUTDOWN_DELAY_MS: &str = "300";
59pub const WASMCLOUD_OCI_ALLOWED_INSECURE: &str = "WASMCLOUD_OCI_ALLOWED_INSECURE";
60pub const WASMCLOUD_OCI_ALLOW_LATEST: &str = "WASMCLOUD_OCI_ALLOW_LATEST";
61
62// Extra configuration (logs, IPV6, config service)
63pub const WASMCLOUD_LOG_LEVEL: &str = "WASMCLOUD_LOG_LEVEL";
64pub const WASMCLOUD_HOST_LOG_PATH: &str = "WASMCLOUD_HOST_LOG_PATH";
65pub const WASMCLOUD_HOST_PATH: &str = "WASMCLOUD_HOST_PATH";
66pub const DEFAULT_STRUCTURED_LOG_LEVEL: &str = "info";
67pub const WASMCLOUD_ENABLE_IPV6: &str = "WASMCLOUD_ENABLE_IPV6";
68pub const WASMCLOUD_STRUCTURED_LOGGING_ENABLED: &str = "WASMCLOUD_STRUCTURED_LOGGING_ENABLED";
69pub const WASMCLOUD_CONFIG_SERVICE: &str = "WASMCLOUD_CONFIG_SERVICE";
70pub const WASMCLOUD_ALLOW_FILE_LOAD: &str = "WASMCLOUD_ALLOW_FILE_LOAD";
71pub const DEFAULT_ALLOW_FILE_LOAD: &str = "true";
72
73/// Helper function to convert WasmcloudOpts to the host environment map.
74/// Takes NatsOpts as well to provide reasonable defaults
75pub async fn configure_host_env(wasmcloud_opts: WasmcloudOpts) -> Result<HashMap<String, String>> {
76    let mut host_config = HashMap::new();
77    // NATS isolation configuration variables
78    host_config.insert(
79        WASMCLOUD_LATTICE.to_string(),
80        wasmcloud_opts
81            .lattice
82            .unwrap_or(DEFAULT_LATTICE.to_string()),
83    );
84    if let Some(js_domain) = wasmcloud_opts.wasmcloud_js_domain {
85        host_config.insert(WASMCLOUD_JS_DOMAIN.to_string(), js_domain);
86    }
87
88    // Host / Cluster configuration
89    if let Some(seed) = wasmcloud_opts.host_seed {
90        host_config.insert(WASMCLOUD_HOST_SEED.to_string(), seed);
91    }
92    if let Some(seed) = wasmcloud_opts.cluster_seed {
93        host_config.insert(WASMCLOUD_CLUSTER_SEED.to_string(), seed);
94    }
95    if let Some(cluster_issuers) = wasmcloud_opts.cluster_issuers {
96        host_config.insert(
97            WASMCLOUD_CLUSTER_ISSUERS.to_string(),
98            cluster_issuers.join(","),
99        );
100    }
101    host_config.insert(
102        WASMCLOUD_MAX_EXECUTION_TIME_MS.to_string(),
103        wasmcloud_opts.max_execution_time.to_string(),
104    );
105    if let Some(policy_topic) = wasmcloud_opts.policy_topic {
106        host_config.insert(WASMCLOUD_POLICY_TOPIC.to_string(), policy_topic.to_string());
107    }
108
109    if let Some(secrets_topic) = wasmcloud_opts.secrets_topic {
110        host_config.insert(
111            WASMCLOUD_SECRETS_TOPIC.to_string(),
112            secrets_topic.to_string(),
113        );
114    }
115
116    if wasmcloud_opts.allow_latest {
117        host_config.insert(WASMCLOUD_OCI_ALLOW_LATEST.to_string(), "true".to_string());
118    }
119    if let Some(allowed_insecure) = wasmcloud_opts.allowed_insecure {
120        host_config.insert(
121            WASMCLOUD_OCI_ALLOWED_INSECURE.to_string(),
122            allowed_insecure.join(","),
123        );
124    }
125
126    // NATS RPC connection configuration
127    if let Some(host) = wasmcloud_opts.rpc_host {
128        host_config.insert(WASMCLOUD_RPC_HOST.to_string(), host.clone());
129    }
130    if let Some(port) = wasmcloud_opts.rpc_port {
131        host_config.insert(WASMCLOUD_RPC_PORT.to_string(), port.to_string());
132    }
133    if let Some(rpc_timeout_ms) = wasmcloud_opts.rpc_timeout_ms {
134        host_config.insert(
135            WASMCLOUD_RPC_TIMEOUT_MS.to_string(),
136            rpc_timeout_ms.to_string(),
137        );
138    }
139    if let Some(path) = wasmcloud_opts.rpc_credsfile {
140        if let Ok((jwt, seed)) = parse_credsfile(path).await {
141            host_config.insert(WASMCLOUD_RPC_JWT.to_string(), jwt.clone());
142            host_config.insert(WASMCLOUD_RPC_SEED.to_string(), seed.clone());
143        };
144    } else {
145        if let Some(jwt) = wasmcloud_opts.rpc_jwt {
146            host_config.insert(WASMCLOUD_RPC_JWT.to_string(), jwt);
147        }
148        if let Some(seed) = wasmcloud_opts.rpc_seed {
149            host_config.insert(WASMCLOUD_RPC_SEED.to_string(), seed);
150        }
151    }
152    if wasmcloud_opts.rpc_tls {
153        host_config.insert(WASMCLOUD_RPC_TLS.to_string(), "true".to_string());
154    }
155
156    // NATS CTL connection configuration
157    if let Some(host) = wasmcloud_opts.ctl_host {
158        host_config.insert(WASMCLOUD_CTL_HOST.to_string(), host);
159    }
160    if let Some(port) = wasmcloud_opts.ctl_port {
161        host_config.insert(WASMCLOUD_CTL_PORT.to_string(), port.to_string());
162    }
163    if let Some(path) = wasmcloud_opts.ctl_credsfile {
164        if let Ok((jwt, seed)) = parse_credsfile(path).await {
165            host_config.insert(WASMCLOUD_CTL_JWT.to_string(), jwt);
166            host_config.insert(WASMCLOUD_CTL_SEED.to_string(), seed);
167        };
168    } else {
169        if let Some(seed) = wasmcloud_opts.ctl_seed {
170            host_config.insert(WASMCLOUD_CTL_SEED.to_string(), seed);
171        }
172        if let Some(jwt) = wasmcloud_opts.ctl_jwt {
173            host_config.insert(WASMCLOUD_CTL_JWT.to_string(), jwt);
174        }
175    }
176    if wasmcloud_opts.ctl_tls {
177        host_config.insert(WASMCLOUD_CTL_TLS.to_string(), "true".to_string());
178    }
179
180    host_config.insert(
181        WASMCLOUD_PROV_SHUTDOWN_DELAY_MS.to_string(),
182        wasmcloud_opts.provider_delay.to_string(),
183    );
184
185    // Extras configuration
186    if wasmcloud_opts.config_service_enabled {
187        host_config.insert(WASMCLOUD_CONFIG_SERVICE.to_string(), "true".to_string());
188    }
189    if wasmcloud_opts.allow_file_load.unwrap_or_default() {
190        host_config.insert(WASMCLOUD_ALLOW_FILE_LOAD.to_string(), "true".to_string());
191    }
192    if wasmcloud_opts.enable_structured_logging {
193        host_config.insert(
194            WASMCLOUD_STRUCTURED_LOGGING_ENABLED.to_string(),
195            "true".to_string(),
196        );
197    }
198
199    let labels: Vec<(String, String)> = wasmcloud_opts
200        .label
201        .unwrap_or_default()
202        .iter()
203        .map(
204            |labelpair| match labelpair.split('=').collect::<Vec<&str>>()[..] {
205                [k, v] => Ok((k.to_string(), v.to_string())),
206                _ => Err(anyhow!(
207                    "invalid label format `{labelpair}`. Expected `key=value`"
208                )),
209            },
210        )
211        .collect::<Result<Vec<(String, String)>>>()?;
212    for (key, value) in labels {
213        host_config.insert(format!("WASMCLOUD_LABEL_{key}"), value.to_string());
214    }
215
216    host_config.insert(
217        WASMCLOUD_LOG_LEVEL.to_string(),
218        wasmcloud_opts.structured_log_level,
219    );
220    if wasmcloud_opts.enable_ipv6 {
221        host_config.insert(WASMCLOUD_ENABLE_IPV6.to_string(), "true".to_string());
222    }
223    Ok(host_config)
224}