mockforge_http/handlers/
failure_designer.rs1use axum::extract::{Path, Query, State};
4use axum::response::Json;
5use mockforge_chaos::failure_designer::{FailureDesignRule, FailureDesigner};
6use mockforge_chaos::ChaosScenario;
7use serde::{Deserialize, Serialize};
8use serde_json::{json, Value};
9use std::sync::Arc;
10
11#[derive(Clone)]
13pub struct FailureDesignerState {
14 pub designer: Arc<FailureDesigner>,
16}
17
18impl FailureDesignerState {
19 pub fn new() -> Self {
21 Self {
22 designer: Arc::new(FailureDesigner::new()),
23 }
24 }
25}
26
27impl Default for FailureDesignerState {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33#[derive(Debug, Deserialize)]
35pub struct ValidateRuleRequest {
36 pub rule: FailureDesignRule,
38}
39
40#[derive(Debug, Deserialize)]
42pub struct GenerateScenarioRequest {
43 pub rule: FailureDesignRule,
45}
46
47#[derive(Debug, Serialize)]
49pub struct ValidateRuleResponse {
50 pub success: bool,
52 #[serde(skip_serializing_if = "Option::is_none")]
54 pub error: Option<String>,
55}
56
57#[derive(Debug, Serialize)]
59pub struct GenerateScenarioResponse {
60 pub success: bool,
62 pub scenario: ChaosScenario,
64 pub route_chaos_config: Value,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub webhook_hook: Option<Value>,
69}
70
71pub async fn validate_rule(
75 State(state): State<FailureDesignerState>,
76 Json(request): Json<ValidateRuleRequest>,
77) -> Json<Value> {
78 let designer = &state.designer;
79 match designer.validate_rule(&request.rule) {
80 Ok(()) => Json(json!({
81 "success": true,
82 })),
83 Err(e) => Json(json!({
84 "success": false,
85 "error": e,
86 })),
87 }
88}
89
90pub async fn generate_scenario(
94 State(state): State<FailureDesignerState>,
95 Json(request): Json<GenerateScenarioRequest>,
96) -> Result<Json<Value>, String> {
97 let designer = &state.designer;
98
99 let scenario = designer
101 .rule_to_scenario(&request.rule)
102 .map_err(|e| format!("Failed to generate scenario: {}", e))?;
103
104 let route_chaos_config = designer
106 .generate_route_chaos_config(&request.rule)
107 .map_err(|e| format!("Failed to generate route chaos config: {}", e))?;
108
109 let webhook_hook = if matches!(
111 request.rule.failure_type,
112 mockforge_chaos::failure_designer::FailureType::WebhookFailure { .. }
113 ) {
114 Some(
115 designer
116 .generate_webhook_hook(&request.rule)
117 .map_err(|e| format!("Failed to generate webhook hook: {}", e))?,
118 )
119 } else {
120 None
121 };
122
123 Ok(Json(json!({
124 "success": true,
125 "scenario": scenario,
126 "route_chaos_config": route_chaos_config,
127 "webhook_hook": webhook_hook,
128 })))
129}
130
131pub async fn preview_config(
135 State(state): State<FailureDesignerState>,
136 Json(request): Json<GenerateScenarioRequest>,
137) -> Result<Json<Value>, String> {
138 let designer = &state.designer;
139
140 designer
142 .validate_rule(&request.rule)
143 .map_err(|e| format!("Validation failed: {}", e))?;
144
145 let scenario = designer
147 .rule_to_scenario(&request.rule)
148 .map_err(|e| format!("Failed to generate scenario: {}", e))?;
149
150 let route_chaos_config = designer
151 .generate_route_chaos_config(&request.rule)
152 .map_err(|e| format!("Failed to generate route chaos config: {}", e))?;
153
154 let webhook_hook = if matches!(
155 request.rule.failure_type,
156 mockforge_chaos::failure_designer::FailureType::WebhookFailure { .. }
157 ) {
158 Some(
159 designer
160 .generate_webhook_hook(&request.rule)
161 .map_err(|e| format!("Failed to generate webhook hook: {}", e))?,
162 )
163 } else {
164 None
165 };
166
167 Ok(Json(json!({
168 "success": true,
169 "rule": request.rule,
170 "scenario": scenario,
171 "route_chaos_config": route_chaos_config,
172 "webhook_hook": webhook_hook,
173 })))
174}