From 911c00714295c13c7e9ec29941b9bbcc87705776 Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Thu, 18 Dec 2025 17:53:47 -0800 Subject: parse the returned JSON from the nix subcommand this produces a list of secrets, although it doesn't yet do any of the checking to see if the files actually exist, when they were modified, etc. it just prints the parsed data structure. this was kind of a pain to test, I had to make a fake machine config with some secrets and point it to it. we should figure out a way to use Rust's test framework to do that automatically, but that can be in a future CL, and I don't necessarily have to be the one to write it. Change-Id: I4c7d579d61e8f3694fe879998dae0f95baaeea05 --- src/main.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 2ebc97c..eff64b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,10 +3,13 @@ use crate::commands::{ Command, CommandMap, Mode }; use crate::error::*; +use std::collections::HashMap; use std::io::Write; use std::process; use ::clap::Parser; +use ::json::{ self, JsonValue }; + mod commands; mod error; @@ -45,8 +48,9 @@ impl TopLevelMode { }))?; command_map.insert(Command::::new("list", |mode, _params| { - let _secrets = read_secret_metadata(&mode.flake_path, + let secrets = read_secret_metadata(&mode.flake_path, &mode.configuration_name)?; + println!("{:?}", secrets); // TODO do something with them Ok(Some(mode)) @@ -88,6 +92,13 @@ fn default_empty_command() -> Result<()> { } +#[derive(Debug)] +struct Secret { + path: String, + script: String, +} + + fn main() -> () { match main_h() { Ok(()) => { }, @@ -133,7 +144,7 @@ fn prompt(raw: &str) -> Result> { fn read_secret_metadata(flake_path: &str, configuration_name: &str) - -> Result<()> + -> Result> { let mut nix_expression = String::new(); nix_expression.push_str("let config = (builtins.getFlake \""); @@ -164,10 +175,41 @@ fn read_secret_metadata(flake_path: &str, configuration_name: &str) } let nix_json = String::from_utf8(nix_output.stdout)?; + let mut nix_json = json::parse(&nix_json).map_err(|e| Error::Internal( + "nix subprocess returned invalid JSON".to_string()))?; + if !nix_json.is_object() { + return Err(Error::Internal( + "nix subprocess returned non-object for JSON".to_string())); + } - println!("{}", nix_json); - // TODO parse the JSON + let mut secrets = HashMap::new(); + for (name, body) in nix_json.entries_mut() { + if !body.is_object() { + return Err(Error::Internal( + "nix subprocess returned non-object for secret definition" + .to_string())); + } - Ok(()) + if !body.has_key("path") { + return Err(Error::Internal( + "nix subprocess returned secret definition with missing path value" + .to_string())); + } + let path = body["path"].take_string().ok_or(Error::Internal( + "nix subprocess returned non-string for path value".to_string()))?; + + if !body.has_key("script") { + return Err(Error::Internal( + "nix subprocess returned secret definition with missing script value" + .to_string())); + } + let script = body["script"].take_string().ok_or(Error::Internal( + "nix subprocess returned non-string for script value" + .to_string()))?; + + secrets.insert(name.to_string(), Secret { path, script }); + } + + Ok(secrets) } -- cgit 1.4.1