]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: add --check-config commandline switch 3412/head
authorPieter Lexis <pieter.lexis@powerdns.com>
Fri, 19 Feb 2016 15:30:47 +0000 (16:30 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Fri, 19 Feb 2016 15:47:08 +0000 (16:47 +0100)
This allows testing of the configuration before one will try to restart
dnsdist with a broken config. Additionally, add tests to confirm the
config check still works.

docs/manpages/dnsdist.1.md
pdns/dnsdist.cc
regression-tests.dnsdist/test_CheckConfig.py [new file with mode: 0644]

index f24cd4dc5cee09ba5d068eaa8d17101b055dd61c..003e81c86cf332b3b8b2fa1bed49c0662f8a577b 100644 (file)
@@ -47,6 +47,11 @@ Server for example is often mentioned.
 -C,--config *FILE*
 :    Load configuration from *FILE*.
 
+--check-config
+:    Test the configuration file (which may be set with **--config** or **-c**)
+     for errors. dnsdist will show the errors and exit with a non-zero exit-code
+     when errors are found.
+
 -c,--client
 :    Operate as a client, connect to dnsdist.
 
index aa77c1483a36a6431b46e710fb33eeb51e4baf05..1aed77a37dd51fed217d5877820b1ed4def00236 100644 (file)
@@ -1153,6 +1153,7 @@ struct
 {
   vector<string> locals;
   vector<string> remotes;
+  bool checkConfig{false};
   bool beDaemon{false};
   bool beClient{false};
   bool beSupervised{false};
@@ -1196,6 +1197,7 @@ try
   struct option longopts[]={ 
     {"acl", required_argument, 0, 'a'},
     {"config", required_argument, 0, 'C'},
+    {"check-config", 0, 0, 1},
     {"execute", required_argument, 0, 'e'},
     {"client", 0, 0, 'c'},
     {"gid",  required_argument, 0, 'g'},
@@ -1216,6 +1218,9 @@ try
     if(c==-1)
       break;
     switch(c) {
+    case 1:
+      g_cmdLine.checkConfig=true;
+      break;
     case 'C':
       g_cmdLine.config=optarg;
       break;
@@ -1303,6 +1308,13 @@ try
     g_ACL.setState(acl);
   }
 
+  if (g_cmdLine.checkConfig) {
+    setupLua(true, g_cmdLine.config);
+    // No exception was thrown
+    infolog("Configuration '%s' OK!", g_cmdLine.config);
+    _exit(0);
+  }
+
   auto todo=setupLua(false, g_cmdLine.config);
 
   if(g_cmdLine.locals.size()) {
diff --git a/regression-tests.dnsdist/test_CheckConfig.py b/regression-tests.dnsdist/test_CheckConfig.py
new file mode 100644 (file)
index 0000000..3c2d1ed
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+import unittest
+import os
+import subprocess
+
+class TestCheckConfig(unittest.TestCase):
+
+    def tryDNSDist(self, configTemplate, shouldBeSuccessful = True):
+        conffile = 'dnsdist_test.conf'
+        with open(conffile, 'w') as conf:
+            conf.write("-- Autogenerated by dnsdisttests.py\n")
+            conf.write(configTemplate)
+
+        dnsdistcmd = [os.environ['DNSDISTBIN'], '-C', conffile, '--check-config']
+
+        with open(os.devnull, 'w') as fdDevNull:
+            dnsdist = subprocess.Popen(dnsdistcmd, close_fds=True, stdout=fdDevNull)
+
+        if dnsdist.poll() is not None:
+            if dnsdist.returncode != 0 and not shouldBeSuccessful:
+                sys.exit(1)
+            sys.exit(0)
+
+    def testWorkingConfig(self):
+        configTemplate = """
+            newServer{address="127.0.0.1:53"}
+            truncateTC(true)
+            addAnyTCRule()
+            addAction(RegexRule("evil[0-9]{4,}\\\\.regex\\\\.tests\\\\.powerdns\\\\.com$"), RCodeAction(5))
+            mySMN = newSuffixMatchNode()
+            mySMN:add(newDNSName("nameAndQtype.tests.powerdns.com."))
+            addAction(AndRule{SuffixMatchNodeRule(mySMN), QTypeRule("TXT")}, RCodeAction(4))
+            addAction(makeRule("drop.test.powerdns.com."), DropAction())
+            block=newDNSName("powerdns.org.")
+            function blockFilter(dq)
+                if(dq.qname:isPartOf(block))
+                then
+                    print("Blocking *.powerdns.org")
+                    return true
+                end
+                return false
+            end
+        """
+
+        self.tryDNSDist(configTemplate)
+
+    def testEmptyConfig(self):
+        configTemplate = ""
+        self.tryDNSDist(configTemplate)
+
+    def testInvalidFunction(self):
+        configTemplate = """
+          oldServer { address="127.0.0.1:55" }
+        """
+        self.tryDNSDist(configTemplate, False)
+
+    def testInvalidParam(self):
+        configTemplate = """
+          newServer { address="127.0.0.355" }
+        """
+        self.tryDNSDist(configTemplate, False)
+
+    def testSyntaxError(self):
+        configTemplate = "blablabla"
+        self.tryDNSDist(configTemplate, False)