Complete protobuf integration for all API endpoints
- Update fetch_config to use protobuf instead of JSON - Add conversion functions from protobuf types to internal config types - Update heartbeat to use protobuf encoding - All API endpoints now use Protocol Buffers (config, metrics, heartbeat) - Reduces 7 unused struct warnings to 1 (HeartbeatResponse)
This commit is contained in:
parent
efea6e3c64
commit
f383f55c13
1 changed files with 118 additions and 6 deletions
|
|
@ -1,7 +1,10 @@
|
|||
use crate::config::{AgentConfig, HeartbeatMetadata};
|
||||
use crate::config::{
|
||||
AgentConfig, EquipmentConfig, HeartbeatMetadata, InterfaceConfig, SensorConfig, SnmpConfig,
|
||||
};
|
||||
use crate::metrics::Metric;
|
||||
use crate::proto::agent;
|
||||
use prost::Message;
|
||||
use std::io::Read;
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
|
||||
|
|
@ -35,7 +38,7 @@ impl ApiClient {
|
|||
Ok(Self { base_url, token })
|
||||
}
|
||||
|
||||
/// Fetch configuration from the API
|
||||
/// Fetch configuration from the API using Protocol Buffers
|
||||
pub async fn fetch_config(&self) -> Result<AgentConfig> {
|
||||
let url = format!("{}/api/v1/agent/config", self.base_url);
|
||||
let token = self.token.clone();
|
||||
|
|
@ -43,6 +46,7 @@ impl ApiClient {
|
|||
let config = tokio::task::spawn_blocking(move || {
|
||||
let response = ureq::get(&url)
|
||||
.set("Authorization", &format!("Bearer {}", token))
|
||||
.set("Accept", "application/x-protobuf")
|
||||
.timeout(Duration::from_secs(30))
|
||||
.call()
|
||||
.map_err(|e| ApiError::RequestFailed(e.to_string()))?;
|
||||
|
|
@ -52,10 +56,20 @@ impl ApiClient {
|
|||
return Err(ApiError::StatusError(status));
|
||||
}
|
||||
|
||||
let config: AgentConfig = response
|
||||
.into_json()
|
||||
// Read response bytes
|
||||
let mut bytes = Vec::new();
|
||||
response
|
||||
.into_reader()
|
||||
.read_to_end(&mut bytes)
|
||||
.map_err(|e| ApiError::RequestFailed(e.to_string()))?;
|
||||
|
||||
// Decode protobuf
|
||||
let proto_config = agent::AgentConfig::decode(&bytes[..])
|
||||
.map_err(|e| ApiError::RequestFailed(format!("Protobuf decode error: {}", e)))?;
|
||||
|
||||
// Convert to internal config type
|
||||
let config = convert_proto_to_config(proto_config);
|
||||
|
||||
Ok(config)
|
||||
})
|
||||
.await
|
||||
|
|
@ -111,16 +125,31 @@ impl ApiClient {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Send heartbeat to the API
|
||||
/// Send heartbeat to the API using Protocol Buffers
|
||||
pub async fn heartbeat(&self, metadata: HeartbeatMetadata) -> Result<()> {
|
||||
let url = format!("{}/api/v1/agent/heartbeat", self.base_url);
|
||||
let token = self.token.clone();
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
// Convert to protobuf
|
||||
let proto_metadata = agent::HeartbeatMetadata {
|
||||
version: metadata.version,
|
||||
hostname: metadata.hostname,
|
||||
uptime_seconds: metadata.uptime_seconds,
|
||||
};
|
||||
|
||||
// Encode to bytes
|
||||
let mut buf = Vec::new();
|
||||
proto_metadata
|
||||
.encode(&mut buf)
|
||||
.map_err(|e| ApiError::RequestFailed(format!("Protobuf encoding error: {}", e)))?;
|
||||
|
||||
// Send as protobuf
|
||||
let response = ureq::post(&url)
|
||||
.set("Authorization", &format!("Bearer {}", token))
|
||||
.set("Content-Type", "application/x-protobuf")
|
||||
.timeout(Duration::from_secs(30))
|
||||
.send_json(&metadata)
|
||||
.send_bytes(&buf)
|
||||
.map_err(|e| ApiError::RequestFailed(e.to_string()))?;
|
||||
|
||||
let status = response.status();
|
||||
|
|
@ -137,6 +166,89 @@ impl ApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
/// Convert protobuf AgentConfig to internal AgentConfig
|
||||
fn convert_proto_to_config(proto: agent::AgentConfig) -> AgentConfig {
|
||||
AgentConfig {
|
||||
version: proto.version,
|
||||
poll_interval_seconds: proto.poll_interval_seconds as u64,
|
||||
equipment: proto
|
||||
.equipment
|
||||
.into_iter()
|
||||
.map(convert_proto_equipment)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert protobuf Equipment to internal EquipmentConfig
|
||||
fn convert_proto_equipment(proto: agent::Equipment) -> EquipmentConfig {
|
||||
EquipmentConfig {
|
||||
id: proto.id,
|
||||
name: proto.name,
|
||||
ip_address: proto.ip_address,
|
||||
snmp: convert_proto_snmp(proto.snmp.unwrap_or_default()),
|
||||
poll_interval_seconds: proto.poll_interval_seconds as u64,
|
||||
sensors: proto
|
||||
.sensors
|
||||
.into_iter()
|
||||
.map(convert_proto_sensor)
|
||||
.collect(),
|
||||
interfaces: proto
|
||||
.interfaces
|
||||
.into_iter()
|
||||
.map(convert_proto_interface)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert protobuf SnmpConfig to internal SnmpConfig
|
||||
fn convert_proto_snmp(proto: agent::SnmpConfig) -> SnmpConfig {
|
||||
SnmpConfig {
|
||||
enabled: proto.enabled,
|
||||
version: proto.version,
|
||||
community: proto.community,
|
||||
port: proto.port as u16,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert protobuf Sensor to internal SensorConfig
|
||||
fn convert_proto_sensor(proto: agent::Sensor) -> SensorConfig {
|
||||
SensorConfig {
|
||||
id: proto.id,
|
||||
sensor_type: proto.r#type,
|
||||
oid: proto.oid,
|
||||
divisor: if proto.divisor == 0.0 {
|
||||
None
|
||||
} else {
|
||||
Some(proto.divisor as i32)
|
||||
},
|
||||
unit: if proto.unit.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(proto.unit)
|
||||
},
|
||||
metadata: if proto.metadata.is_empty() {
|
||||
None
|
||||
} else {
|
||||
// Convert metadata map to JSON value
|
||||
let json_map: serde_json::Map<String, serde_json::Value> = proto
|
||||
.metadata
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, serde_json::Value::String(v)))
|
||||
.collect();
|
||||
Some(serde_json::Value::Object(json_map))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert protobuf Interface to internal InterfaceConfig
|
||||
fn convert_proto_interface(proto: agent::Interface) -> InterfaceConfig {
|
||||
InterfaceConfig {
|
||||
id: proto.id,
|
||||
if_index: proto.if_index as i32,
|
||||
if_name: proto.if_name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert internal Metric type to protobuf Metric
|
||||
fn convert_metric_to_proto(metric: &Metric) -> agent::Metric {
|
||||
use crate::metrics::Metric as M;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue