]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec api: add subtree option to the cache flush endpoint
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Wed, 2 May 2018 12:07:13 +0000 (14:07 +0200)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Wed, 2 May 2018 12:16:49 +0000 (14:16 +0200)
pdns/recursordist/docs/http-api/endpoint-cache.rst
pdns/ws-recursor.cc
regression-tests.api/runtests.py
regression-tests.api/test_Cache.py
regression-tests.api/test_helper.py

index 7a7848debca2542b2f4796a0b6cc07d6591590e2..4b642f32d53586c29074d01db1fbeaebf152c988 100644 (file)
@@ -7,6 +7,7 @@ Cache manipulation endpoint
 
   :query server_id: The name of the server
   :query domain: The domainname to flush for
+  :query subtree: If set to `true`, also flush the whole subtree (default=`false`)
 
   **Example Response:**
 
index 2d153f7dc9217c46e087c32c2a409dc8b8ad0c71..a9991dfefeab21e73f9557f1b4a63092d1d38630 100644 (file)
@@ -373,10 +373,11 @@ static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) {
     throw HttpMethodNotAllowedException();
 
   DNSName canon = apiNameToDNSName(req->getvars["domain"]);
+  bool subtree = (req->getvars["subtree"].compare("true") == 0);
 
-  int count = broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon, false));
-  count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, canon, false));
-  count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon, false));
+  int count = broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon, subtree));
+  count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, canon, subtree));
+  count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon, subtree));
   resp->setBody(Json::object {
     { "count", count },
     { "result", "Flushed cache." }
index 9d2fb6c602992f5f3d66f0e769808f64ba76adc9..6278815e6a593c42da96de4d3aec504ea7204525 100755 (executable)
@@ -185,6 +185,8 @@ test_env.update({
     'DAEMON': daemon,
     'SQLITE_DB': SQLITE_DB,
     'PDNSUTIL_CMD': ' '.join(PDNSUTIL_CMD),
+    'SDIG': sdig,
+    'DNSPORT': str(DNSPORT)
 })
 
 try:
index 6a3f618d51cf84686dafbeb5c83590009be2faf1..ad2c8503c9ecac2858de6e5c71aac0134f631cee 100644 (file)
@@ -1,4 +1,4 @@
-from test_helper import ApiTestCase, is_auth, is_recursor
+from test_helper import ApiTestCase, is_auth, is_recursor, sdig
 
 
 class Servers(ApiTestCase):
@@ -9,6 +9,28 @@ class Servers(ApiTestCase):
         data = r.json()
         self.assertIn('count', data)
 
+    def test_flush_count(self):
+        sdig("ns1.example.com", 'A')
+        r = self.session.put(self.url("/api/v1/servers/localhost/cache/flush?domain=ns1.example.com."))
+        self.assert_success_json(r)
+        data = r.json()
+        self.assertIn('count', data)
+        self.assertEquals(1, data['count'])
+
+    def test_flush_subtree(self):
+        sdig("ns1.example.com", 'A')
+        sdig("ns2.example.com", 'A')
+        r = self.session.put(self.url("/api/v1/servers/localhost/cache/flush?domain=example.com.&subtree=false"))
+        self.assert_success_json(r)
+        data = r.json()
+        self.assertIn('count', data)
+        self.assertEquals(1, data['count'])
+        r = self.session.put(self.url("/api/v1/servers/localhost/cache/flush?domain=example.com.&subtree=true"))
+        self.assert_success_json(r)
+        data = r.json()
+        self.assertIn('count', data)
+        self.assertEquals(2, data['count'])
+
     def test_flush_root(self):
         r = self.session.put(self.url("/api/v1/servers/localhost/cache/flush?domain=."))
         self.assert_success_json(r)
index 8c1dfd3759a30202c98f6f38aea71c49fbd223ee..2affa83a4ba176e4c895941c4f5501abffc3775e 100644 (file)
@@ -11,11 +11,11 @@ if sys.version_info[0] == 2:
 else:
     from urllib.parse import urljoin
 
-
 DAEMON = os.environ.get('DAEMON', 'authoritative')
 PDNSUTIL_CMD = os.environ.get('PDNSUTIL_CMD', 'NOT_SET BUT_THIS MIGHT_BE_A_LIST').split(' ')
 SQLITE_DB = os.environ.get('SQLITE_DB', 'pdns.sqlite3')
-
+SDIG = os.environ.get('SDIG', 'sdig')
+DNSPORT = os.environ.get('DNSPORT', '53')
 
 class ApiTestCase(unittest.TestCase):
 
@@ -86,7 +86,12 @@ def pdnsutil(subcommand, *args):
     except subprocess.CalledProcessError as except_inst:
         raise RuntimeError("pdnsutil %s %s failed: %s" % (command, args, except_inst.output.decode('ascii', errors='replace')))
 
-
 def pdnsutil_rectify(zonename):
     """Run pdnsutil rectify-zone on the given zone."""
     pdnsutil('rectify-zone', zonename)
+
+def sdig(*args):
+    try:
+        return subprocess.check_call([SDIG, '127.0.0.1', str(DNSPORT)] + list(args))
+    except subprocess.CalledProcessError as except_inst:
+        raise RuntimeError("sdig %s %s failed: %s" % (command, args, except_inst.output.decode('ascii', errors='replace')))