]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Implement OT conditions REST delete call
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 14 Jan 2026 12:44:39 +0000 (13:44 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 14 Jan 2026 12:44:39 +0000 (13:44 +0100)
Signed-off-by: Otto Moerbeek <otto.moerbeek@open-xchange.com>
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-rust-lib/rust/src/bridge.hh
pdns/recursordist/rec-rust-lib/rust/src/web.rs
pdns/recursordist/rec-web-stubs.hh
pdns/recursordist/rec_channel.hh
pdns/recursordist/rec_channel_rec.cc
pdns/recursordist/ws-recursor.cc

index b06b482d25bc3f8d649840d64a8aa46329777eb4..c577e031c6cf589d1a9d002b8a90879b6e134206 100644 (file)
@@ -1485,7 +1485,6 @@ void broadcastFunction(const pipefunc_t& func)
     */
     func();
   }
-
   unsigned int thread = 0;
   for (const auto& threadInfo : RecThreadInfo::infos()) {
     if (thread++ == RecThreadInfo::thread_local_id()) {
index c18f0866a1704dcdff3b28324bda209ea6b949cb..3e5b114aaaee56120b58120a237b4df3953646d4 100644 (file)
@@ -100,4 +100,5 @@ void apiServerZoneDetailPUT(const Request& rustRequest, Response& rustResponse);
 void apiServerZoneDetailDELETE(const Request& rustRequest, Response& rustResponse);
 void apiServerOTConditionsGET(const Request& rustRequest, Response& rustResponse);
 void apiServerOTConditionDetailGET(const Request& rustRequest, Response& rustResponse);
+void apiServerOTConditionDetailDELETE(const Request& rustRequest, Response& rustResponse);
 }
index 5d043d5ab5e6df4e507b511e36c48e1b194e673d..3ae2557323c987168592b5b6b59c1262ccecaed8 100644 (file)
@@ -413,6 +413,17 @@ fn matcher(
             }
             *apifunc = Some(rustweb::apiServerOTConditionDetailGET)
         }
+        (&Method::DELETE, ["api", "v1", "servers", "localhost", "otconditions", id]) => {
+            let decoded = form_urlencoded::parse(id.as_bytes());
+            // decoded should contain a single key without value
+            if let Some(kv) = decoded.last() {
+                request.parameters.push(rustweb::KeyValue {
+                    key: String::from("id"),
+                    value: kv.0.to_string(),
+                });
+            }
+            *apifunc = Some(rustweb::apiServerOTConditionDetailDELETE)
+        }
         _ => *filefunc = Some(file),
     }
 }
@@ -1162,6 +1173,7 @@ mod rustweb {
         fn apiServerZonesPOST(requst: &Request, response: &mut Response) -> Result<()>;
         fn apiServerOTConditionsGET(request: &Request, response: &mut Response) -> Result<()>;
         fn apiServerOTConditionDetailGET(request: &Request, response: &mut Response) -> Result<()>;
+        fn apiServerOTConditionDetailDELETE(request: &Request, response: &mut Response) -> Result<()>;
         fn jsonstat(request: &Request, response: &mut Response) -> Result<()>;
         fn prometheusMetrics(request: &Request, response: &mut Response) -> Result<()>;
         fn serveStuff(request: &Request, response: &mut Response) -> Result<()>;
index cedc574626f7cab1d516ac011f50e01da311a14f..2f17cabf49a086f7999b0c7768a04df197f31225 100644 (file)
@@ -28,6 +28,7 @@ WRAPPER(apiServerZonesGET)
 WRAPPER(apiServerZonesPOST)
 WRAPPER(apiServerOTConditionsGET)
 WRAPPER(apiServerOTConditionDetailGET)
+WRAPPER(apiServerOTConditionDetailDELETE)
 WRAPPER(jsonstat)
 WRAPPER(prometheusMetrics)
 WRAPPER(serveStuff)
index aaa115edec5380cb1f3d76becd2de9e921aa30f7..f23bd788e6684b61c8bc4a0fa5da2b11784e01fd 100644 (file)
@@ -152,3 +152,5 @@ void registerAllStats();
 void doExitNicely();
 RecursorControlChannel::Answer doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
 RecursorControlChannel::Answer luaconfig(bool broadcast);
+struct OpenTelemetryTraceCondition;
+void updateOTConditions(const NetmaskTree<OpenTelemetryTraceCondition>& conditions);
index 40cc4c022a130435da77271be6f3e8f9bec9cdb3..c1148b593e12d02940bb8554c423e153264d17ba 100644 (file)
@@ -1988,6 +1988,11 @@ static void* pleaseSupplantOTConditions(const OpenTelemetryTraceConditions& cond
   return nullptr;
 }
 
+void updateOTConditions(const OpenTelemetryTraceConditions& conditions)
+{
+  broadcastFunction([conditions] { return pleaseSupplantOTConditions(conditions); });
+}
+
 static RecursorControlChannel::Answer help(ArgIterator /* begin */, ArgIterator /* end */)
 {
   static const std::map<std::string, std::string> commands = {
index 61c8f77d9082dd7ccfb8312a42218a6bd59da31e..2bea2c128a6473ee4e595bdc5b4d92f60e00a1c0 100644 (file)
@@ -584,7 +584,7 @@ static void fillOTCondition(const Netmask& netmask, HttpResponse* resp)
   auto lock = g_initialOpenTelemetryConditions.lock();
   if (*lock) {
     auto condition = (*lock)->lookup(netmask);
-    if (condition != nullptr) {
+    if (condition != nullptr && condition->first == netmask) { // exact match
       Json::object object{
         {"acl", condition->first.toString()},
         {"edns_option_required", condition->second.d_edns_option_required},
@@ -625,6 +625,29 @@ static void apiServerOTConditionDetailGET(HttpRequest* req, HttpResponse* resp)
   }
 }
 
+static void apiServerOTConditionDetailDELETE(HttpRequest* req, HttpResponse* resp)
+{
+  try {
+    Netmask netmask{req->parameters["id"]};
+    auto lock = g_initialOpenTelemetryConditions.lock();
+    if (*lock) {
+      auto condition = (*lock)->lookup(netmask);
+      if (condition != nullptr && condition->first == netmask) { // exact match
+        (*lock)->erase(condition->first);
+        updateOTConditions(**lock);
+        // empty body on success
+        resp->body = "";
+        resp->status = 204; // No Content: declare that the condition is gone now
+        return;
+      }
+    }
+    throw ApiException("Could not find otcondition '" + netmask.toString() + "'");
+  }
+  catch (NetmaskException& ex) {
+    throw ApiException("Could not parse netmask");
+  }
+}
+
 static void prometheusMetrics(HttpRequest* /* req */, HttpResponse* resp)
 {
   static MetricDefinitionStorage s_metricDefinitions;
@@ -1199,6 +1222,7 @@ WRAPPER(apiServerZonesGET)
 WRAPPER(apiServerZonesPOST)
 WRAPPER(apiServerOTConditionsGET)
 WRAPPER(apiServerOTConditionDetailGET)
+WRAPPER(apiServerOTConditionDetailDELETE)
 WRAPPER(prometheusMetrics)
 WRAPPER(serveStuff)