use tonic::{Request, Response, Status};
use std::collections::HashMap;
use crate::proto::moby::secrets::v1::{
secrets_server::Secrets,
GetSecretRequest, GetSecretResponse,
};
const MAX_SECRET_SIZE: usize = 500 * 1024;
#[derive(Debug, Clone, Default)]
pub struct SecretsServer {
secrets: HashMap<String, Vec<u8>>,
}
impl SecretsServer {
pub fn new() -> Self {
Self {
secrets: HashMap::new(),
}
}
pub fn add_secret(&mut self, id: impl Into<String>, data: Vec<u8>) -> Result<(), String> {
if data.len() > MAX_SECRET_SIZE {
return Err(format!("Secret size {} exceeds maximum of {}", data.len(), MAX_SECRET_SIZE));
}
self.secrets.insert(id.into(), data);
Ok(())
}
pub fn add_secret_string(&mut self, id: impl Into<String>, value: impl AsRef<str>) -> Result<(), String> {
self.add_secret(id, value.as_ref().as_bytes().to_vec())
}
pub fn from_map(secrets: HashMap<String, String>) -> Result<Self, String> {
let mut server = Self::new();
for (id, value) in secrets {
server.add_secret_string(id, value)?;
}
Ok(server)
}
}
#[tonic::async_trait]
impl Secrets for SecretsServer {
async fn get_secret(
&self,
request: Request<GetSecretRequest>,
) -> Result<Response<GetSecretResponse>, Status> {
let req = request.into_inner();
tracing::debug!("Secret requested - ID: {}, Annotations: {:?}", req.id, req.annotations);
if let Some(data) = self.secrets.get(&req.id) {
tracing::debug!("Found secret '{}' ({} bytes)", req.id, data.len());
Ok(Response::new(GetSecretResponse {
data: data.clone(),
}))
} else {
tracing::warn!("Secret '{}' not found", req.id);
Err(Status::not_found(format!("secret {} not found", req.id)))
}
}
}