vta_cli_common/commands/
config.rs1use std::collections::HashMap;
2
3use vta_sdk::prelude::*;
4use vta_sdk::protocols::vta_management::update_config::UpdateConfigBody;
5
6pub async fn cmd_config_get(
11 client: &VtaClient,
12 label_prefix: &str,
13) -> Result<(), Box<dyn std::error::Error>> {
14 let resp = client.get_config().await?;
15 let width = resp
17 .config
18 .fields
19 .iter()
20 .map(|f| f.key.len() + 1)
21 .max()
22 .unwrap_or(0)
23 .max(12);
24 for field in &resp.config.fields {
25 let value = match &field.value {
26 serde_json::Value::Null => "(not set)".to_string(),
27 serde_json::Value::String(s) => s.clone(),
28 other => other.to_string(),
29 };
30 let restart = if field.requires_restart {
31 " (requires restart)"
32 } else {
33 ""
34 };
35 println!(
36 "{label_prefix}{:<width$} {value} [{}]{restart}",
37 format!("{}:", field.key),
38 field.source
39 );
40 }
41 Ok(())
42}
43
44pub async fn cmd_config_update(
53 client: &VtaClient,
54 label_prefix: &str,
55 vta_name: Option<String>,
56 public_url: Option<String>,
57) -> Result<(), Box<dyn std::error::Error>> {
58 cmd_config_patch(
59 client,
60 label_prefix,
61 vta_name,
62 public_url,
63 RateLimitOverrides::default(),
64 )
65 .await
66}
67
68#[derive(Debug, Default, Clone, Copy)]
72#[non_exhaustive]
73pub struct RateLimitOverrides {
74 pub rate_limit_interval_secs: Option<u64>,
76 pub rate_limit_burst: Option<u32>,
78 pub did_log_rate_limit_interval_secs: Option<u64>,
81 pub did_log_rate_limit_burst: Option<u32>,
83}
84
85impl RateLimitOverrides {
86 fn entries(&self) -> Vec<(&'static str, serde_json::Value)> {
88 [
89 (
90 vta_sdk::rate_limit::VTA_INTERVAL_KEY,
91 self.rate_limit_interval_secs.map(serde_json::Value::from),
92 ),
93 (
94 vta_sdk::rate_limit::VTA_BURST_KEY,
95 self.rate_limit_burst.map(serde_json::Value::from),
96 ),
97 (
98 vta_sdk::rate_limit::VTA_DID_LOG_INTERVAL_KEY,
99 self.did_log_rate_limit_interval_secs
100 .map(serde_json::Value::from),
101 ),
102 (
103 vta_sdk::rate_limit::VTA_DID_LOG_BURST_KEY,
104 self.did_log_rate_limit_burst.map(serde_json::Value::from),
105 ),
106 ]
107 .into_iter()
108 .filter_map(|(k, v)| v.map(|v| (k, v)))
109 .collect()
110 }
111}
112
113pub async fn cmd_config_patch(
116 client: &VtaClient,
117 label_prefix: &str,
118 vta_name: Option<String>,
119 public_url: Option<String>,
120 rate_limits: RateLimitOverrides,
121) -> Result<(), Box<dyn std::error::Error>> {
122 let mut overrides = HashMap::new();
123 if let Some(v) = vta_name {
124 overrides.insert("vta_name".to_string(), serde_json::Value::String(v));
125 }
126 if let Some(v) = public_url {
127 overrides.insert("public_url".to_string(), serde_json::Value::String(v));
128 }
129 for (key, value) in rate_limits.entries() {
130 overrides.insert(key.to_string(), value);
131 }
132 if overrides.is_empty() {
133 println!(
134 "Nothing to update — pass at least one of --vta-name, --public-url, \
135 --rate-limit-interval-secs, --rate-limit-burst, \
136 --did-log-rate-limit-interval-secs or --did-log-rate-limit-burst."
137 );
138 return Ok(());
139 }
140
141 let resp = client
142 .update_config(UpdateConfigRequest {
143 patch: UpdateConfigBody::new(overrides),
144 })
145 .await?;
146
147 if !resp.applied.is_empty() {
148 println!(
149 "{label_prefix}Applied: {}",
150 resp.applied.join(", ")
151 );
152 }
153 if !resp.pending_restart.is_empty() {
154 println!(
155 "{label_prefix}Pending restart: {}",
156 resp.pending_restart.join(", ")
157 );
158 println!("{label_prefix} Stored, but not in effect until the VTA restarts.");
159 }
160 for rejected in &resp.rejected {
161 println!(
162 "{label_prefix}Rejected {}: {}",
163 rejected.key, rejected.reason
164 );
165 }
166 Ok(())
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn rate_limit_overrides_emit_only_set_keys_as_integers() {
175 assert!(RateLimitOverrides::default().entries().is_empty());
176
177 let o = RateLimitOverrides {
178 rate_limit_burst: Some(30),
179 did_log_rate_limit_interval_secs: Some(2),
180 ..Default::default()
181 };
182 let entries = o.entries();
183 assert_eq!(
184 entries,
185 vec![
186 ("rate_limit_burst", serde_json::json!(30)),
187 ("did_log_rate_limit_interval_secs", serde_json::json!(2)),
188 ]
189 );
190 }
191}