Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/rndc_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ fn primary_list(input: &str) -> IResult<&str, Vec<PrimarySpec>> {

/// Statement types within a zone configuration
#[derive(Debug)]
#[allow(dead_code)]
enum ZoneStatement {
// Core
Type(ZoneType),
Expand Down
1 change: 0 additions & 1 deletion src/rndc_types_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#[cfg(test)]
mod tests {
use crate::rndc_types::*;
use std::collections::HashMap;

// ========== Enum Tests ==========

Expand Down
4 changes: 4 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub enum ApiError {
#[error("Zone not found: {0}")]
ZoneNotFound(String),

#[error("Zone already exists: {0}")]
ZoneAlreadyExists(String),

#[error("Internal server error: {0}")]
InternalError(String),
}
Expand All @@ -55,6 +58,7 @@ impl IntoResponse for ApiError {
ApiError::RndcError(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
ApiError::InvalidRequest(_) => (StatusCode::BAD_REQUEST, self.to_string()),
ApiError::ZoneNotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
ApiError::ZoneAlreadyExists(_) => (StatusCode::CONFLICT, self.to_string()),
ApiError::InternalError(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
};

Expand Down
10 changes: 10 additions & 0 deletions src/types_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ fn test_api_error_zone_not_found() {
assert_eq!(response.status(), StatusCode::NOT_FOUND);
}

#[test]
fn test_api_error_zone_already_exists() {
let error = ApiError::ZoneAlreadyExists("example.com".to_string());
assert_eq!(error.to_string(), "Zone already exists: example.com");

let response = error.into_response();
assert_eq!(response.status(), StatusCode::CONFLICT);
}

#[test]
fn test_api_error_internal_error() {
let error = ApiError::InternalError("Database connection failed".to_string());
Expand All @@ -110,6 +119,7 @@ fn test_api_error_display() {
ApiError::RndcError("rndc error".to_string()),
ApiError::InvalidRequest("invalid".to_string()),
ApiError::ZoneNotFound("test.com".to_string()),
ApiError::ZoneAlreadyExists("test.com".to_string()),
ApiError::InternalError("internal".to_string()),
];

Expand Down
10 changes: 9 additions & 1 deletion src/zones.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ pub struct ZoneListResponse {
responses(
(status = 201, description = "Zone created successfully", body = ZoneResponse),
(status = 400, description = "Invalid request"),
(status = 409, description = "Zone already exists"),
(status = 500, description = "RNDC command failed"),
(status = 500, description = "Internal server error")
),
Expand Down Expand Up @@ -441,7 +442,14 @@ pub async fn create_zone(
.map_err(|e| {
error!("RNDC addzone failed for {}: {}", request.zone_name, e);
metrics::record_zone_operation("create", false);
ApiError::RndcError(e.to_string())

// Check if zone already exists
let error_msg = e.to_string();
if error_msg.contains("already exists") {
ApiError::ZoneAlreadyExists(request.zone_name.clone())
} else {
ApiError::RndcError(error_msg)
}
})?;

info!("Zone {} created successfully", request.zone_name);
Expand Down