Page MenuHomePhabricator

network.rs
No OneTemporary

network.rs

use std::sync::Arc;
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use serde::{Deserialize, Serialize};
use store::network::{BasicAssigner, BasicProvider, NetRange, RangeAssigner};
use crate::AppState;
#[derive(Serialize, Deserialize)]
pub struct CreateNetworkRequest {
pub name: String,
pub cidr: String,
pub provider_type: Option<String>,
pub provider_config: Option<serde_json::Value>,
pub assigner_type: Option<String>,
pub assigner_config: Option<serde_json::Value>,
}
pub async fn get_networks(State(state): State<Arc<AppState>>) -> impl IntoResponse {
let networks = state.collar.store.networks();
match networks.list() {
Ok(network_list) => (StatusCode::OK, Json(network_list)).into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to list networks: {:?}", e)).into_response(),
}
}
pub async fn post_networks(State(state): State<Arc<AppState>>, Json(req): Json<CreateNetworkRequest>) -> impl IntoResponse {
let networks = state.collar.store.networks();
// Parse the CIDR
let netrange = match NetRange::from_cidr(&req.cidr) {
Ok(range) => range,
Err(e) => return (StatusCode::BAD_REQUEST, format!("Invalid CIDR '{}': {:?}", req.cidr, e)).into_response(),
};
// Create basic provider with optional config
let provider = if let Some(config) = req.provider_config {
BasicProvider::new().with_config("config", &config.to_string())
} else {
BasicProvider::new()
};
// Handle different assigner types with separate create calls
let result = if let Some(assigner_type) = req.assigner_type {
match assigner_type.as_str() {
"basic" => {
let mut basic_assigner = BasicAssigner::new("sequential");
if let Some(config) = req.assigner_config {
basic_assigner = basic_assigner.with_config("config", &config.to_string());
}
networks.create(&req.name, netrange, provider, Some(basic_assigner))
},
"range" => {
if let Some(config) = req.assigner_config {
if let Some(range_name) = config.get("range_name").and_then(|v| v.as_str()) {
let mut range_assigner = RangeAssigner::with_range_name(range_name);
if let Some(extra_config) = config.get("config") {
range_assigner = range_assigner.with_config("config", &extra_config.to_string());
}
networks.create(&req.name, netrange, provider, Some(range_assigner))
} else {
return (StatusCode::BAD_REQUEST, "Range assigner requires 'range_name' in config".to_string()).into_response();
}
} else {
return (StatusCode::BAD_REQUEST, "Range assigner requires config with 'range_name'".to_string()).into_response();
}
},
_ => return (StatusCode::BAD_REQUEST, format!("Unknown assigner type: {}", assigner_type)).into_response(),
}
} else {
networks.create(&req.name, netrange, provider, None::<BasicAssigner>)
};
// Handle the result
match result {
Ok(_) => (StatusCode::OK, format!("Created network '{}'", req.name)).into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to create network '{}': {:?}", req.name, e)).into_response(),
}
}
pub async fn get_network(State(state): State<Arc<AppState>>, Path(name): Path<String>) -> impl IntoResponse {
let networks = state.collar.store.networks();
match networks.get(&name) {
Ok(Some(network)) => {
let network_json = serde_json::json!({
"name": network.name,
"netrange": match network.netrange {
NetRange::V4 { addr, prefix } => {
serde_json::json!({
"type": "v4",
"addr": addr.to_string(),
"prefix": prefix
})
},
NetRange::V6 { addr, prefix } => {
serde_json::json!({
"type": "v6",
"addr": addr.to_string(),
"prefix": prefix
})
}
},
"provider_type": network.provider_type,
"provider_config": serde_json::from_str::<serde_json::Value>(&network.provider_config).unwrap_or(serde_json::Value::Null),
"assigner_type": network.assigner_type,
"assigner_config": network.assigner_config.as_ref()
.and_then(|config| serde_json::from_str::<serde_json::Value>(config).ok())
.unwrap_or(serde_json::Value::Null)
});
(StatusCode::OK, Json(network_json)).into_response()
},
Ok(None) => (StatusCode::NOT_FOUND, format!("Network '{}' not found", name)).into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to get network '{}': {:?}", name, e)).into_response(),
}
}
pub async fn delete_network(State(state): State<Arc<AppState>>, Path(name): Path<String>) -> impl IntoResponse {
let networks = state.collar.store.networks();
match networks.delete(&name) {
Ok(true) => (StatusCode::OK, format!("Deleted network '{}'", name)).into_response(),
Ok(false) => (StatusCode::NOT_FOUND, format!("Network '{}' not found", name)).into_response(),
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to delete network '{}': {:?}", name, e)).into_response(),
}
}

File Metadata

Mime Type
text/plain
Expires
Mon, Jun 9, 11:45 AM (11 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
47644
Default Alt Text
network.rs (5 KB)

Event Timeline