use agent_first_data::ValueSource;
use agent_first_data::value_source::SecretString;
use crate::cli::token_source;
use crate::sdk::Client;
use crate::shared::error::Error;
#[derive(Debug, Clone, Default)]
pub struct Connection {
pub endpoint: Option<String>,
pub token: Option<ValueSource>,
}
#[derive(Debug, Clone)]
pub struct Resolved {
pub endpoint: String,
pub token: Option<SecretString>,
}
impl Connection {
pub fn new(endpoint: Option<String>, token: Option<ValueSource>) -> Self {
Self { endpoint, token }
}
pub fn is_explicit(&self) -> bool {
self.endpoint.is_some()
}
pub async fn resolve(&self) -> Result<Resolved, Error> {
let token = self.token.as_ref().map(token_source::read).transpose()?;
match self.endpoint.as_deref() {
Some(endpoint) => Ok(Resolved {
endpoint: endpoint.to_string(),
token,
}),
None => {
let host = crate::cli::cmd::container::discover_default_local_host(
token.as_ref().map(SecretString::expose_secret),
)
.await?;
Ok(Resolved {
endpoint: host.endpoint,
token: host.token_secret,
})
}
}
}
pub async fn client(&self) -> Result<Client, Error> {
self.resolve().await?.client()
}
}
impl Resolved {
pub fn client(&self) -> Result<Client, Error> {
let client = Client::connect(&self.endpoint)?;
Ok(match &self.token {
Some(token) => client.with_token(token.expose_secret()),
None => client,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn a_named_endpoint_resolves_without_discovery() {
let connection = Connection::new(
Some("ws://127.0.0.1:9222".to_string()),
Some(ValueSource::Literal("t0ken".to_string())),
);
assert!(connection.is_explicit());
let resolved = connection.resolve().await.expect("explicit host resolves");
assert_eq!(resolved.endpoint, "ws://127.0.0.1:9222");
assert_eq!(
resolved.token.as_ref().map(SecretString::expose_secret),
Some("t0ken")
);
}
#[tokio::test]
async fn an_unreadable_token_source_fails_before_the_host_is_touched() {
let connection = Connection::new(
Some("ws://127.0.0.1:9222".to_string()),
Some(ValueSource::Env("AFHTTP_TEST_ABSENT_TOKEN".to_string())),
);
let error = connection.resolve().await.expect_err("unset env source");
assert!(error.detail.contains("--token-secret"), "{}", error.detail);
}
}