]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add API networks and views testing.
authorMiod Vallat <miod.vallat@powerdns.com>
Fri, 11 Apr 2025 08:49:57 +0000 (10:49 +0200)
committerMiod Vallat <miod.vallat@powerdns.com>
Mon, 26 May 2025 11:49:13 +0000 (13:49 +0200)
regression-tests.api/runtests.py
regression-tests.api/test_Views.py [new file with mode: 0644]
regression-tests.api/test_Zones.py
regression-tests/backends/lmdb-master
regression-tests/tests/views-management/command

index b82c6237529c58025d76577f7dc2d87f511adec2..9e8ec5c11f5e5cf59b01cf122cb03d81ac4f56ae 100755 (executable)
@@ -67,6 +67,7 @@ AUTH_LMDB_TPL = """
 # Generated by runtests.py
 launch=lmdb
 lmdb-filename="""+LMDB_DB+"""
+views
 """
 
 AUTH_COMMON_TPL = """
diff --git a/regression-tests.api/test_Views.py b/regression-tests.api/test_Views.py
new file mode 100644 (file)
index 0000000..e4a24b7
--- /dev/null
@@ -0,0 +1,163 @@
+# this tests Networks and Views
+
+import subprocess
+import json
+import unittest
+import os
+
+from test_helper import ApiTestCase, is_auth, is_auth_lmdb, pdnsutil
+from test_Zones import AuthZonesHelperMixin
+
+@unittest.skipIf(not is_auth(), "Not applicable")
+@unittest.skipIf(not is_auth_lmdb(), "Views require the LMDB backend")
+class Networks(ApiTestCase):
+    def setUp(self):
+        super(Networks, self).setUp()
+
+    def tearDown(self):
+        super(Networks, self).tearDown()
+
+    def test_networks(self):
+        r = self.set_network('192.0.2.0/24', view='view1')
+        self.assertEqual(r.status_code, 204)
+        self.assertEqual(r.content, b"")
+
+        # Check network presence
+        nets = self.get_networks()
+        self.assertEqual(nets['192.0.2.0/24'], 'view1')
+
+        # Check individual fetch
+        r = self.get_network('192.0.2.0/24')
+        print(r.content)
+        self.assertEqual(r.status_code, 200)
+        self.assertEqual(r.json()['networks'][0], dict(network='192.0.2.0/24', view='view1'))  # FIXME: should this really be wrapped inside `networks:`?
+
+        # empty view name is equivalent to delete
+        r = self.set_network('192.0.2.0/24', view='')
+        print(r.content)
+        self.assertEqual(r.status_code, 204)
+        self.assertEqual(r.content, b"")
+
+        # Check network absence
+        nets = self.get_networks()
+        self.assertNotIn('192.0.2.0/24', nets)
+
+        # Check individual fetch
+        r = self.get_network('192.0.2.0/24')
+        print(r.content)
+        self.assertEqual(r.status_code, 404)
+
+    def set_network(self, prefix, **content):
+        r = self.session.put(
+            self.url("/api/v1/servers/localhost/networks/"+prefix),
+            data=json.dumps(content),
+            headers={'content-type': 'application/json'})
+
+        return r
+
+    def get_network(self, prefix):
+        r = self.session.get(
+            self.url("/api/v1/servers/localhost/networks/"+prefix),
+            headers={'content-type': 'application/json'})
+
+        return r
+
+    def get_networks(self):
+        r = self.session.get(
+            self.url("/api/v1/servers/localhost/networks"),
+            headers={'content-type': 'application/json'})
+
+        ret = {}
+
+        for netview in r.json()['networks']:
+            net = netview['network']
+            view = netview['view']
+            self.assertNotIn(net, ret)
+            ret[net] = view
+
+        return ret
+
+@unittest.skipIf(not is_auth(), "Not applicable")
+@unittest.skipIf(not is_auth_lmdb(), "Views require the LMDB backend")
+class Views(ApiTestCase, AuthZonesHelperMixin):
+    def setUp(self):
+        super(Views, self).setUp()
+        self.create_zone('example.com..spiceoflife')
+
+    def tearDown(self):
+        super(Views, self).tearDown()
+        self.session.delete(self.url("/api/v1/servers/localhost/zones/example.com..spiceoflife"))
+
+    def _test_views(self, variant=''):
+        zone = 'example.com.' + variant
+        r = self.set_view_zone('view1', zone)
+        self.assertEqual(r.status_code, 204)
+        self.assertEqual(r.content, b"")
+
+        # Check view presence
+        r = self.get_views()
+        self.assertEqual(r.status_code, 200)
+        self.assertIn('view1', r.json()["views"])
+
+        # Check individual fetch
+        r = self.get_view('view1')
+        print(r)
+        self.assertEqual(r.status_code, 200)
+        self.assertEqual(r.json()["zones"], [zone])
+
+        r = self.del_view_zone('view1', zone)
+        print(r.content)
+        self.assertEqual(r.status_code, 204)
+        self.assertEqual(r.content, b"")
+
+        # Check view absence
+        r = self.get_views()
+        self.assertEqual(r.status_code, 200)
+        self.assertNotIn('view1', r.json()["views"])
+
+        # Check individual fetch
+        r = self.get_view('view1')
+        print(r.content)
+        self.assertEqual(r.status_code, 404)
+
+    def test_views_novariant(self):
+        return self._test_views()
+
+    def test_views_variant(self):
+        return self._test_views('.spiceoflife')
+
+    def set_view_zone(self, view, zone):
+        r = self.session.post(
+            self.url("/api/v1/servers/localhost/views/"+view),
+            data=json.dumps(dict(name=zone)),
+            headers={'content-type': 'application/json'})
+
+        self.assertEqual(r.status_code, 204)
+
+        return r
+
+    def del_view_zone(self, view, zone):
+        r = self.session.delete(
+            self.url("/api/v1/servers/localhost/views/"+view+"/"+zone),
+            data=json.dumps(dict(name=zone)),
+            headers={'content-type': 'application/json'})
+
+        self.assertEqual(r.status_code, 204)
+
+        return r
+
+    def get_view(self, view):
+        r = self.session.get(
+            self.url("/api/v1/servers/localhost/views/"+view),
+            headers={'content-type': 'application/json'})
+
+        return r
+
+    def get_views(self):
+        r = self.session.get(
+            self.url("/api/v1/servers/localhost/views"),
+            headers={'content-type': 'application/json'})
+
+        self.assertEqual(r.status_code, 200)
+
+        return r
index 3902376ac238a2507739ca34c8e9ceeeb2daee4e..6538c2ee671b7a5aa2b36b9b0a25d1812c134655 100644 (file)
@@ -456,7 +456,7 @@ class AuthZones(ApiTestCase, AuthZonesHelperMixin):
             data=json.dumps(payload),
             headers={'content-type': 'application/json'})
         self.assertEqual(r.status_code, 422)
-        self.assertIn('Unable to parse DNS Name', r.json()['error'])
+        self.assertIn('Unable to parse Zone Name', r.json()['error'])
 
     def test_create_zone_restricted_chars(self):
         name = 'test:' + unique_zone_name()  # : isn't good as a name.
index a02fd240bfad1af267f9eb519c7c93ac4cd82610..6cdc3b482c83db83c4501cc0b39a9fc9cba9d66e 100644 (file)
@@ -87,7 +87,7 @@ __EOF__
             $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb set-options-json tsig.com$plusvariant '{"producer":{"group":["pdns-group-x","pdns-group-y"]}}'
         fi
 
-        [ -n "$plusvariant" ] && $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb network-set 0.0.0.0/0 variant-view
+        [ -n "$plusvariant" ] && $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb set-network 0.0.0.0/0 variant-view
 
         for variant in foo bar
         do
@@ -106,8 +106,8 @@ __EOF__
         $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb add-record example.org..foo target TXT '"hello from target..foo"'
         $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb view-add-zone view1 example.org..foo
 
-        $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb network-set 192.0.2.0/24 view1
-        $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb network-set 192.0.2.0/25 view2
+        $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb set-network 192.0.2.0/24 view1
+        $RUNWRAPPER_PDNSUTIL $PDNSUTIL --config-dir=. --config-name=lmdb set-network 192.0.2.0/25 view2
 
         $RUNWRAPPER $PDNS --loglevel=7 --daemon=no --local-address=$address --local-port=$port --config-dir=. \
             --config-name=lmdb --socket-dir=./ --no-shuffle \
index fde841f178b88ffc92e3fc4623a91a7df14a4a10..419547383f1fbe8a92e6307dfb30a60c648ca7fd 100755 (executable)
@@ -10,29 +10,29 @@ pdnsutil_wrapper view-add-zone myview example.org..variant3
 set +e
 
 echo == one view
-pdnsutil_wrapper view-list
+pdnsutil_wrapper list-views
 echo == with one zone
-pdnsutil_wrapper view-list myview
+pdnsutil_wrapper list-view myview
 
 pdnsutil_wrapper view-add-zone myotherview example.com
 
 echo == view with one zone
-pdnsutil_wrapper view-list myotherview
+pdnsutil_wrapper list-view myotherview
 
 pdnsutil_wrapper view-add-zone myview example.org..variant2
 pdnsutil_wrapper view-add-zone myview example.net..variant5
 echo == with two zones
-pdnsutil_wrapper view-list myview
+pdnsutil_wrapper list-view myview
 
 pdnsutil_wrapper view-del-zone myview example.org..variant2
 echo == view with one zone
-pdnsutil_wrapper view-list myview
+pdnsutil_wrapper list-view myview
 
 pdnsutil_wrapper view-del-zone myotherview example.com
 echo == one view
-pdnsutil_wrapper view-list
+pdnsutil_wrapper list-views
 
 echo == check proper variant replacement
-pdnsutil_wrapper view-list myview
+pdnsutil_wrapper list-view myview
 pdnsutil_wrapper view-add-zone myview example.net..completelydifferent
-pdnsutil_wrapper view-list myview
+pdnsutil_wrapper list-view myview