diff --git a/crates/brokerd/src/consult.rs b/crates/brokerd/src/consult.rs index 0df00b7..3f70f2f 100644 --- a/crates/brokerd/src/consult.rs +++ b/crates/brokerd/src/consult.rs @@ -4,10 +4,13 @@ use std::ffi::OsString; use std::time::Duration; -use bxcore::secrets::{Loaded, SecretError, SecretSpec}; +use bxcore::secrets::{Loaded, Secret, SecretError, SecretSpec}; use serde::{Deserialize, Deserializer, Serialize}; +use crate::args::ToolArgs; use crate::config::Config; +use crate::policy::Label; +use crate::runner::{RunError, RunOutput, RunSpec, Runtime}; pub const CONSULT: &str = "consult"; /// `question` and the answer are cut to this many bytes, on a character boundary. @@ -241,3 +244,99 @@ pub fn load_secret( .map_err(SecretStartError::Load)?; Ok(Some(loaded)) } + +/// One POST of the allowlisted body. Tests inject a fake; production uses loopback HTTP/1.1. +pub trait ConsultTransport: Send + Sync { + fn post( + &self, + url: &str, + bearer: &str, + body: &[u8], + timeout: Duration, + ) -> Result, String>; +} + +/// Runs an allowed `consult` through `transport`. +pub struct ConsultRuntime { + consult: Consult, + secret: Secret, + transport: T, +} + +impl ConsultRuntime { + pub fn new(consult: Consult, secret: Secret, transport: T) -> ConsultRuntime { + ConsultRuntime { + consult, + secret, + transport, + } + } +} + +impl Runtime for ConsultRuntime { + fn run(&self, spec: &RunSpec) -> Result { + self.run_labelled(spec).map(|(output, _)| output) + } + + fn run_labelled(&self, spec: &RunSpec) -> Result<(RunOutput, Option