re-uploading work
This commit is contained in:
200
crates/core-timer-sensor/src/config.rs
Normal file
200
crates/core-timer-sensor/src/config.rs
Normal file
@@ -0,0 +1,200 @@
|
||||
//! Configuration module for timer sensor
|
||||
//!
|
||||
//! Supports loading configuration from environment variables or stdin JSON.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Read;
|
||||
|
||||
/// Sensor configuration
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SensorConfig {
|
||||
/// Base URL of the Attune API
|
||||
pub api_url: String,
|
||||
|
||||
/// API token for authentication
|
||||
pub api_token: String,
|
||||
|
||||
/// Sensor reference name (e.g., "core.timer")
|
||||
pub sensor_ref: String,
|
||||
|
||||
/// RabbitMQ connection URL
|
||||
pub mq_url: String,
|
||||
|
||||
/// RabbitMQ exchange name (default: "attune")
|
||||
#[serde(default = "default_exchange")]
|
||||
pub mq_exchange: String,
|
||||
|
||||
/// Log level (default: "info")
|
||||
#[serde(default = "default_log_level")]
|
||||
pub log_level: String,
|
||||
}
|
||||
|
||||
fn default_exchange() -> String {
|
||||
"attune".to_string()
|
||||
}
|
||||
|
||||
fn default_log_level() -> String {
|
||||
"info".to_string()
|
||||
}
|
||||
|
||||
impl SensorConfig {
|
||||
/// Load configuration from environment variables
|
||||
pub fn from_env() -> Result<Self> {
|
||||
let api_url = std::env::var("ATTUNE_API_URL")
|
||||
.context("ATTUNE_API_URL environment variable is required")?;
|
||||
|
||||
let api_token = std::env::var("ATTUNE_API_TOKEN")
|
||||
.context("ATTUNE_API_TOKEN environment variable is required")?;
|
||||
|
||||
let sensor_ref = std::env::var("ATTUNE_SENSOR_REF")
|
||||
.context("ATTUNE_SENSOR_REF environment variable is required")?;
|
||||
|
||||
let mq_url = std::env::var("ATTUNE_MQ_URL")
|
||||
.context("ATTUNE_MQ_URL environment variable is required")?;
|
||||
|
||||
let mq_exchange =
|
||||
std::env::var("ATTUNE_MQ_EXCHANGE").unwrap_or_else(|_| default_exchange());
|
||||
|
||||
let log_level = std::env::var("ATTUNE_LOG_LEVEL").unwrap_or_else(|_| default_log_level());
|
||||
|
||||
Ok(Self {
|
||||
api_url,
|
||||
api_token,
|
||||
sensor_ref,
|
||||
mq_url,
|
||||
mq_exchange,
|
||||
log_level,
|
||||
})
|
||||
}
|
||||
|
||||
/// Load configuration from stdin JSON
|
||||
pub async fn from_stdin() -> Result<Self> {
|
||||
let mut buffer = String::new();
|
||||
std::io::stdin()
|
||||
.read_to_string(&mut buffer)
|
||||
.context("Failed to read configuration from stdin")?;
|
||||
|
||||
serde_json::from_str(&buffer).context("Failed to parse JSON configuration from stdin")
|
||||
}
|
||||
|
||||
/// Validate configuration
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
if self.api_url.is_empty() {
|
||||
return Err(anyhow::anyhow!("api_url cannot be empty"));
|
||||
}
|
||||
|
||||
if self.api_token.is_empty() {
|
||||
return Err(anyhow::anyhow!("api_token cannot be empty"));
|
||||
}
|
||||
|
||||
if self.sensor_ref.is_empty() {
|
||||
return Err(anyhow::anyhow!("sensor_ref cannot be empty"));
|
||||
}
|
||||
|
||||
if self.mq_url.is_empty() {
|
||||
return Err(anyhow::anyhow!("mq_url cannot be empty"));
|
||||
}
|
||||
|
||||
if self.mq_exchange.is_empty() {
|
||||
return Err(anyhow::anyhow!("mq_exchange cannot be empty"));
|
||||
}
|
||||
|
||||
// Validate API URL format
|
||||
if !self.api_url.starts_with("http://") && !self.api_url.starts_with("https://") {
|
||||
return Err(anyhow::anyhow!(
|
||||
"api_url must start with http:// or https://"
|
||||
));
|
||||
}
|
||||
|
||||
// Validate MQ URL format
|
||||
if !self.mq_url.starts_with("amqp://") && !self.mq_url.starts_with("amqps://") {
|
||||
return Err(anyhow::anyhow!(
|
||||
"mq_url must start with amqp:// or amqps://"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_config_validation() {
|
||||
let config = SensorConfig {
|
||||
api_url: "http://localhost:8080".to_string(),
|
||||
api_token: "test_token".to_string(),
|
||||
sensor_ref: "core.timer".to_string(),
|
||||
mq_url: "amqp://localhost:5672".to_string(),
|
||||
mq_exchange: "attune".to_string(),
|
||||
log_level: "info".to_string(),
|
||||
};
|
||||
|
||||
assert!(config.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_validation_invalid_api_url() {
|
||||
let config = SensorConfig {
|
||||
api_url: "localhost:8080".to_string(), // Missing http://
|
||||
api_token: "test_token".to_string(),
|
||||
sensor_ref: "core.timer".to_string(),
|
||||
mq_url: "amqp://localhost:5672".to_string(),
|
||||
mq_exchange: "attune".to_string(),
|
||||
log_level: "info".to_string(),
|
||||
};
|
||||
|
||||
assert!(config.validate().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_validation_invalid_mq_url() {
|
||||
let config = SensorConfig {
|
||||
api_url: "http://localhost:8080".to_string(),
|
||||
api_token: "test_token".to_string(),
|
||||
sensor_ref: "core.timer".to_string(),
|
||||
mq_url: "localhost:5672".to_string(), // Missing amqp://
|
||||
mq_exchange: "attune".to_string(),
|
||||
log_level: "info".to_string(),
|
||||
};
|
||||
|
||||
assert!(config.validate().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_deserialization() {
|
||||
let json = r#"{
|
||||
"api_url": "http://localhost:8080",
|
||||
"api_token": "test_token",
|
||||
"sensor_ref": "core.timer",
|
||||
"mq_url": "amqp://localhost:5672"
|
||||
}"#;
|
||||
|
||||
let config: SensorConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.api_url, "http://localhost:8080");
|
||||
assert_eq!(config.api_token, "test_token");
|
||||
assert_eq!(config.sensor_ref, "core.timer");
|
||||
assert_eq!(config.mq_url, "amqp://localhost:5672");
|
||||
assert_eq!(config.mq_exchange, "attune"); // Default
|
||||
assert_eq!(config.log_level, "info"); // Default
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_deserialization_with_optionals() {
|
||||
let json = r#"{
|
||||
"api_url": "http://localhost:8080",
|
||||
"api_token": "test_token",
|
||||
"sensor_ref": "core.timer",
|
||||
"mq_url": "amqp://localhost:5672",
|
||||
"mq_exchange": "custom",
|
||||
"log_level": "debug"
|
||||
}"#;
|
||||
|
||||
let config: SensorConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.mq_exchange, "custom");
|
||||
assert_eq!(config.log_level, "debug");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user