|
1 |
| -use std::path::Path; |
2 |
| - |
| 1 | +use age::x25519::Identity; |
3 | 2 | use bollard::{
|
4 | 3 | network::ListNetworksOptions,
|
5 | 4 | service::{ContainerSummary, Volume},
|
6 | 5 | volume::ListVolumesOptions,
|
7 | 6 | };
|
| 7 | +use linked_hash_map::LinkedHashMap; |
| 8 | +use std::path::Path; |
8 | 9 |
|
9 | 10 | use crate::{
|
10 |
| - age_utils, |
| 11 | + age_utils::{self, Variable}, |
11 | 12 | api::WorkspaceApi,
|
| 13 | + cli::{ConfigPart, WorkParams, WorkspacePersistence}, |
12 | 14 | constants,
|
13 | 15 | labels::{self, Labels, ROLE},
|
14 | 16 | model::{
|
15 |
| - config::FinalCfg, |
| 17 | + config::{ConfigSource, FileFormat, FinalCfg, RoozCfg}, |
16 | 18 | types::{AnyError, ContainerResult, RunSpec, WorkSpec, WorkspaceResult},
|
17 | 19 | volume::{RoozVolume, CACHE_ROLE, WORK_ROLE},
|
18 | 20 | },
|
@@ -200,11 +202,143 @@ impl<'a> WorkspaceApi<'a> {
|
200 | 202 | Ok(())
|
201 | 203 | }
|
202 | 204 |
|
203 |
| - pub async fn show_config(&self, workspace_key: &str) -> Result<(), AnyError> { |
| 205 | + pub async fn show_config(&self, workspace_key: &str, part: ConfigPart) -> Result<(), AnyError> { |
| 206 | + let labels = Labels::new(Some(workspace_key), Some(WORK_ROLE)); |
| 207 | + for c in self.api.container.get_all(&labels).await? { |
| 208 | + if let Some(labels) = c.labels { |
| 209 | + println!( |
| 210 | + "{}", |
| 211 | + labels[match part { |
| 212 | + ConfigPart::OriginPath => labels::CONFIG_ORIGIN, |
| 213 | + ConfigPart::OriginBody => labels::CONFIG_BODY, |
| 214 | + ConfigPart::Runtime => labels::RUNTIME_CONFIG, |
| 215 | + }] |
| 216 | + ); |
| 217 | + } |
| 218 | + } |
| 219 | + Ok(()) |
| 220 | + } |
| 221 | + |
| 222 | + pub fn encrypt( |
| 223 | + &self, |
| 224 | + identity: Identity, |
| 225 | + name: &str, |
| 226 | + vars: LinkedHashMap<String, String>, |
| 227 | + ) -> Result<LinkedHashMap<String, String>, AnyError> { |
| 228 | + let encrypted = self.encrypt_value(identity, vars[name].to_string())?; |
| 229 | + let mut new_vars = vars.clone(); |
| 230 | + new_vars.insert(name.to_string(), encrypted); |
| 231 | + Ok(new_vars) |
| 232 | + } |
| 233 | + |
| 234 | + pub fn encrypt_value( |
| 235 | + &self, |
| 236 | + identity: Identity, |
| 237 | + clear_text: String, |
| 238 | + ) -> Result<String, AnyError> { |
| 239 | + age_utils::encrypt(clear_text, identity.to_public()) |
| 240 | + } |
| 241 | + |
| 242 | + pub async fn decrypt( |
| 243 | + &self, |
| 244 | + vars: Option<LinkedHashMap<String, String>>, |
| 245 | + ) -> Result<LinkedHashMap<String, age_utils::Variable>, AnyError> { |
| 246 | + log::debug!("Checking if vars need decryption"); |
| 247 | + if let Some(vars) = age_utils::needs_decryption(vars.clone()) { |
| 248 | + log::debug!("Decrypting vars"); |
| 249 | + let identity = self.read_age_identity().await?; |
| 250 | + age_utils::decrypt(&identity, vars) |
| 251 | + } else { |
| 252 | + log::debug!("No encrypted vars found"); |
| 253 | + let mut ret = LinkedHashMap::<String, Variable>::new(); |
| 254 | + match vars { |
| 255 | + Some(vars) => { |
| 256 | + for (k, v) in vars { |
| 257 | + ret.insert(k, Variable::ClearText { value: v }); |
| 258 | + } |
| 259 | + Ok(ret) |
| 260 | + } |
| 261 | + None => Ok(ret), |
| 262 | + } |
| 263 | + } |
| 264 | + } |
| 265 | + |
| 266 | + pub fn variables_to_string( |
| 267 | + &self, |
| 268 | + vars: &LinkedHashMap<String, Variable>, |
| 269 | + ) -> LinkedHashMap<String, String> { |
| 270 | + let mut ret = LinkedHashMap::<String, String>::new(); |
| 271 | + for (k, v) in vars { |
| 272 | + ret.insert(k.clone(), v.to_string()); |
| 273 | + } |
| 274 | + ret |
| 275 | + } |
| 276 | + |
| 277 | + pub async fn edit(&self, workspace_key: &str) -> Result<(), AnyError> { |
204 | 278 | let labels = Labels::new(Some(workspace_key), Some(WORK_ROLE));
|
205 | 279 | for c in self.api.container.get_all(&labels).await? {
|
206 | 280 | if let Some(labels) = c.labels {
|
207 |
| - println!("{}", labels[labels::RUNTIME_CONFIG]); |
| 281 | + let config_source = &labels[labels::CONFIG_ORIGIN]; |
| 282 | + let format = FileFormat::from_path(config_source); |
| 283 | + let config = |
| 284 | + RoozCfg::deserialize_config(&labels[labels::CONFIG_BODY], format)?.unwrap(); |
| 285 | + let decrypted = self.decrypt(config.clone().vars).await?; |
| 286 | + let decrypted_config = RoozCfg { |
| 287 | + vars: if decrypted.len() > 0 { |
| 288 | + Some(self.variables_to_string(&decrypted)) |
| 289 | + } else { |
| 290 | + None |
| 291 | + }, |
| 292 | + ..config |
| 293 | + }; |
| 294 | + |
| 295 | + let decrypted_string = decrypted_config.to_string(format)?; |
| 296 | + let edited_string = edit::edit(decrypted_string.clone())?; |
| 297 | + |
| 298 | + if edited_string != decrypted_string { |
| 299 | + let edited_config = RoozCfg::from_string(&edited_string, format)?; |
| 300 | + let identity = self.read_age_identity().await?; |
| 301 | + |
| 302 | + let mut encrypted_vars = LinkedHashMap::<String, String>::new(); |
| 303 | + for (k, v) in &decrypted { |
| 304 | + let edited_value = &edited_config.clone().vars.unwrap()[k]; |
| 305 | + match v { |
| 306 | + Variable::ClearText { .. } => { |
| 307 | + encrypted_vars.insert(k.to_string(), edited_value.to_string()) |
| 308 | + } |
| 309 | + Variable::Secret { .. } => encrypted_vars.insert( |
| 310 | + k.to_string(), |
| 311 | + self.encrypt_value(identity.clone(), edited_value.to_string())?, |
| 312 | + ), |
| 313 | + }; |
| 314 | + } |
| 315 | + |
| 316 | + let encrypted_config = RoozCfg { |
| 317 | + vars: if encrypted_vars.len() > 0 { |
| 318 | + Some(encrypted_vars) |
| 319 | + } else { |
| 320 | + None |
| 321 | + }, |
| 322 | + ..edited_config |
| 323 | + }; |
| 324 | + |
| 325 | + self.new( |
| 326 | + &WorkParams { |
| 327 | + ..Default::default() |
| 328 | + }, |
| 329 | + Some(ConfigSource::Body { |
| 330 | + value: encrypted_config, |
| 331 | + origin: config_source.to_string(), |
| 332 | + format, |
| 333 | + }), |
| 334 | + Some(WorkspacePersistence { |
| 335 | + name: labels[labels::WORKSPACE_KEY].to_string(), |
| 336 | + replace: false, |
| 337 | + apply: true, |
| 338 | + }), |
| 339 | + ) |
| 340 | + .await?; |
| 341 | + } |
208 | 342 | }
|
209 | 343 | }
|
210 | 344 | Ok(())
|
|
0 commit comments