wash_lib/context/
mod.rs

1//! Types and methods for handling wash contexts, the configuration files for interacting with
2//! lattices
3
4use std::path::PathBuf;
5
6use anyhow::Result;
7use serde::{Deserialize, Serialize};
8use serde_with::{serde_as, NoneAsEmptyString};
9
10use crate::{
11    config::{
12        DEFAULT_COMPONENT_OPERATION_TIMEOUT_MS, DEFAULT_LATTICE, DEFAULT_NATS_HOST,
13        DEFAULT_NATS_PORT, DEFAULT_NATS_TIMEOUT_MS,
14    },
15    id::ClusterSeed,
16};
17
18pub mod fs;
19
20pub const HOST_CONFIG_NAME: &str = "host_config";
21
22/// A trait that can be implemented by any type that wants to load, save, and otherwise manage wash
23/// contexts (e.g. from a database or a config store
24// NOTE(thomastaylor312): We may want to make this an async trait in the future since any other
25// implementation than the fs one will likely involve networking
26pub trait ContextManager {
27    /// Returns the name of the currently set default context.
28    fn default_context_name(&self) -> Result<String>;
29
30    /// Sets the current default context to the given name. Should error if it doesn't exist
31    fn set_default_context(&self, name: &str) -> Result<()>;
32
33    /// Saves the given context
34    fn save_context(&self, ctx: &WashContext) -> Result<()>;
35
36    /// Deletes named context. If this context is the current default context, the default context
37    /// should be unset
38    fn delete_context(&self, name: &str) -> Result<()>;
39
40    /// Loads the currently set default context
41    fn load_default_context(&self) -> Result<WashContext>;
42
43    /// Loads the named context
44    fn load_context(&self, name: &str) -> Result<WashContext>;
45
46    /// Returns a list of all context names
47    fn list_contexts(&self) -> Result<Vec<String>>;
48}
49
50#[serde_as]
51#[derive(Clone, Deserialize, Serialize, Debug)]
52pub struct WashContext {
53    #[serde(default)]
54    pub name: String,
55    #[serde_as(as = "NoneAsEmptyString")]
56    pub cluster_seed: Option<ClusterSeed>,
57
58    #[serde(default = "default_nats_host")]
59    pub ctl_host: String,
60    #[serde(default = "default_nats_port")]
61    pub ctl_port: u16,
62    #[serde_as(as = "NoneAsEmptyString")]
63    pub ctl_jwt: Option<String>,
64    #[serde_as(as = "NoneAsEmptyString")]
65    pub ctl_seed: Option<String>,
66    pub ctl_credsfile: Option<PathBuf>,
67    /// timeout in milliseconds
68    #[serde(default = "default_timeout_ms")]
69    pub ctl_timeout: u64,
70    /// TLS CA file to use for CTL
71    pub ctl_tls_ca_file: Option<PathBuf>,
72    /// Perform TLS handshake before expecting the server greeting for CTL
73    pub ctl_tls_first: Option<bool>,
74
75    // NOTE: lattice_prefix was renamed to lattice in most places, but this alias will need to remain for backwards compatibility with existing context files
76    #[serde(alias = "lattice_prefix", default = "default_lattice")]
77    pub lattice: String,
78
79    pub js_domain: Option<String>,
80
81    #[serde(default = "default_nats_host")]
82    pub rpc_host: String,
83    #[serde(default = "default_nats_port")]
84    pub rpc_port: u16,
85    #[serde_as(as = "NoneAsEmptyString")]
86    pub rpc_jwt: Option<String>,
87    #[serde_as(as = "NoneAsEmptyString")]
88    pub rpc_seed: Option<String>,
89    pub rpc_credsfile: Option<PathBuf>,
90    /// rpc timeout in milliseconds
91    #[serde(default = "default_timeout_ms")]
92    pub rpc_timeout: u64,
93    /// TLS CA file to use for RPC calls
94    pub rpc_tls_ca_file: Option<PathBuf>,
95    /// Perform TLS handshake before expecting the server greeting for RPC
96    pub rpc_tls_first: Option<bool>,
97}
98
99impl WashContext {
100    /// Create a new default context with the given name
101    #[must_use]
102    pub fn named(name: String) -> Self {
103        WashContext {
104            name,
105            ..Self::default()
106        }
107    }
108}
109
110impl Default for WashContext {
111    fn default() -> Self {
112        WashContext {
113            name: "default".to_string(),
114            cluster_seed: None,
115            ctl_host: DEFAULT_NATS_HOST.to_string(),
116            ctl_port: DEFAULT_NATS_PORT.parse().unwrap(),
117            ctl_jwt: None,
118            ctl_seed: None,
119            ctl_credsfile: None,
120            ctl_timeout: DEFAULT_NATS_TIMEOUT_MS,
121            ctl_tls_ca_file: None,
122            ctl_tls_first: None,
123            lattice: DEFAULT_LATTICE.to_string(),
124            js_domain: None,
125            rpc_host: DEFAULT_NATS_HOST.to_string(),
126            rpc_port: DEFAULT_NATS_PORT.parse().unwrap(),
127            rpc_jwt: None,
128            rpc_seed: None,
129            rpc_credsfile: None,
130            rpc_timeout: DEFAULT_NATS_TIMEOUT_MS,
131            rpc_tls_ca_file: None,
132            rpc_tls_first: None,
133        }
134    }
135}
136
137// Below are required functions for serde default derive with WashContext
138
139fn default_nats_host() -> String {
140    DEFAULT_NATS_HOST.to_string()
141}
142
143fn default_nats_port() -> u16 {
144    DEFAULT_NATS_PORT.parse().unwrap()
145}
146
147fn default_lattice() -> String {
148    DEFAULT_LATTICE.to_string()
149}
150
151#[must_use]
152pub fn default_timeout_ms() -> u64 {
153    DEFAULT_NATS_TIMEOUT_MS
154}
155
156/// Default timeout that should be used with operations that manipulate components (ex. scale)
157#[must_use]
158pub fn default_component_operation_timeout_ms() -> u64 {
159    DEFAULT_COMPONENT_OPERATION_TIMEOUT_MS
160}