mockforge_intelligence/handlers/
failure_designer.rs1use axum::{extract::State, response::Json};
3use serde::{de::DeserializeOwned, Deserialize, Serialize};
4use serde_json::{json, Value};
5
6pub trait FailureDesignerProvider: Clone + Send + Sync + 'static {
8 type Rule: DeserializeOwned + Serialize + Send + Sync + 'static;
10 type Scenario: Serialize;
12 fn validate_rule(&self, rule: &Self::Rule) -> Result<(), String>;
14 fn rule_to_scenario(&self, rule: &Self::Rule) -> Result<Self::Scenario, String>;
16 fn generate_route_chaos_config(&self, rule: &Self::Rule) -> Result<Value, String>;
18 fn webhook_hook(&self, rule: &Self::Rule) -> Result<Option<Value>, String>;
20}
21
22#[derive(Debug, Deserialize)]
24pub struct ValidateRuleRequest<R> {
25 pub rule: R,
27}
28
29#[derive(Debug, Deserialize)]
31pub struct GenerateScenarioRequest<R> {
32 pub rule: R,
34}
35
36#[derive(Debug, Serialize)]
38pub struct ValidateRuleResponse {
39 pub success: bool,
41 #[serde(skip_serializing_if = "Option::is_none")]
43 pub error: Option<String>,
44}
45
46#[derive(Debug, Serialize)]
48pub struct GenerateScenarioResponse<C> {
49 pub success: bool,
51 pub scenario: C,
53 pub route_chaos_config: Value,
55 #[serde(skip_serializing_if = "Option::is_none")]
57 pub webhook_hook: Option<Value>,
58}
59
60pub async fn validate_rule<S: FailureDesignerProvider>(
64 State(state): State<S>,
65 Json(request): Json<ValidateRuleRequest<S::Rule>>,
66) -> Json<Value> {
67 let designer = &state;
68 match designer.validate_rule(&request.rule) {
69 Ok(()) => Json(json!({
70 "success": true,
71 })),
72 Err(e) => Json(json!({
73 "success": false,
74 "error": e,
75 })),
76 }
77}
78
79pub async fn generate_scenario<S: FailureDesignerProvider>(
83 State(state): State<S>,
84 Json(request): Json<GenerateScenarioRequest<S::Rule>>,
85) -> Result<Json<Value>, String> {
86 let designer = &state;
87
88 let scenario = designer
90 .rule_to_scenario(&request.rule)
91 .map_err(|e| format!("Failed to generate scenario: {}", e))?;
92
93 let route_chaos_config = designer
95 .generate_route_chaos_config(&request.rule)
96 .map_err(|e| format!("Failed to generate route chaos config: {}", e))?;
97
98 let webhook_hook = designer
100 .webhook_hook(&request.rule)
101 .map_err(|e| format!("Failed to generate webhook hook: {}", e))?;
102
103 Ok(Json(json!({
104 "success": true,
105 "scenario": scenario,
106 "route_chaos_config": route_chaos_config,
107 "webhook_hook": webhook_hook,
108 })))
109}
110
111pub async fn preview_config<S: FailureDesignerProvider>(
115 State(state): State<S>,
116 Json(request): Json<GenerateScenarioRequest<S::Rule>>,
117) -> Result<Json<Value>, String> {
118 let designer = &state;
119
120 designer
122 .validate_rule(&request.rule)
123 .map_err(|e| format!("Validation failed: {}", e))?;
124
125 let scenario = designer
127 .rule_to_scenario(&request.rule)
128 .map_err(|e| format!("Failed to generate scenario: {}", e))?;
129
130 let route_chaos_config = designer
131 .generate_route_chaos_config(&request.rule)
132 .map_err(|e| format!("Failed to generate route chaos config: {}", e))?;
133
134 let webhook_hook = designer
135 .webhook_hook(&request.rule)
136 .map_err(|e| format!("Failed to generate webhook hook: {}", e))?;
137
138 Ok(Json(json!({
139 "success": true,
140 "rule": request.rule,
141 "scenario": scenario,
142 "route_chaos_config": route_chaos_config,
143 "webhook_hook": webhook_hook,
144 })))
145}