]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Make a combination of delete and replace for rrset possible 8623/head
authorJonathan Eenkhoorn <jonathan.eenkhoorn@antagonist.nl>
Thu, 12 Dec 2019 09:36:23 +0000 (10:36 +0100)
committerJonathan Eenkhoorn <jonathan.eenkhoorn@antagonist.nl>
Fri, 20 Dec 2019 11:19:38 +0000 (12:19 +0100)
pdns/ws-auth.cc
pdns/ws-auth.hh
regression-tests.api/test_Zones.py

index 85d64d7752f44383bf036c182c1f0b774927fac4..18e5024eb5431feaf2185252f2a3bc47b468bfbd 100644 (file)
@@ -1965,7 +1965,7 @@ static void patchZone(UeberBackend& B, HttpRequest* req, HttpResponse* resp) {
     di.backend->getDomainMetadataOne(zonename, "SOA-EDIT", soa_edit_kind);
     bool soa_edit_done = false;
 
-    set<pair<DNSName, QType>> seen;
+    set<tuple<DNSName, QType, string>> seen;
 
     for (const auto& rrset : rrsets.array_items()) {
       string changetype = toUpper(stringFromJson(rrset, "changetype"));
@@ -1977,11 +1977,11 @@ static void patchZone(UeberBackend& B, HttpRequest* req, HttpResponse* resp) {
         throw ApiException("RRset "+qname.toString()+" IN "+stringFromJson(rrset, "type")+": unknown type given");
       }
 
-      if(seen.count({qname, qtype}))
+      if(seen.count({qname, qtype, changetype}))
       {
-        throw ApiException("Duplicate RRset "+qname.toString()+" IN "+qtype.getName());
+        throw ApiException("Duplicate RRset "+qname.toString()+" IN "+qtype.getName()+" with changetype: "+changetype);
       }
-      seen.insert({qname, qtype});
+      seen.insert({qname, qtype, changetype});
 
       if (changetype == "DELETE") {
         // delete all matching qname/qtype RRs (and, implicitly comments).
index e42ec43baaa40b6effa4d1fa9f461d7587c68f13..a8ffe17adc071ace437e044e779a243e64019cba 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef WS_HH
 #define WS_HH
 #include <string>
+#include <tuple>
 #include <map>
 #include <time.h>
 #include <pthread.h>
index c7fbe2758bb46eff529dd706813a5ebaa87e0a28..77f2441047ed80c7809a84c9824f13f33c56bc41 100644 (file)
@@ -1184,6 +1184,35 @@ $ORIGIN %NAME%
         data = self.session.get(self.url("/api/v1/servers/localhost/zones/" + name)).json()
         self.assertIsNone(get_rrset(data, name, 'NS'))
 
+    def test_zone_rr_update_rrset_combine_replace_and_delete(self):
+        name, payload, zone = self.create_zone()
+        rrset1 = {
+            'changetype': 'delete',
+            'name': 'sub.' + name,
+            'type': 'CNAME',
+        }
+        rrset2 = {
+            'changetype': 'replace',
+            'name': 'sub.' + name,
+            'type': 'CNAME',
+            'ttl': 500,
+            'records': [
+                {
+                    "content": "www.example.org.",
+                    "disabled": False
+                }
+            ]
+        }
+        payload = {'rrsets': [rrset1, rrset2]}
+        r = self.session.patch(
+            self.url("/api/v1/servers/localhost/zones/" + name),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+        self.assert_success(r)
+        # verify that (only) the new record is there
+        data = self.session.get(self.url("/api/v1/servers/localhost/zones/" + name)).json()
+        self.assertEquals(get_rrset(data, 'sub.' + name, 'CNAME')['records'], rrset2['records'])
+
     def test_zone_disable_reenable(self):
         # This also tests that SOA-EDIT-API works.
         name, payload, zone = self.create_zone(soa_edit_api='EPOCH')