From: Pieter Lexis Date: Fri, 19 Feb 2016 15:30:47 +0000 (+0100) Subject: dnsdist: add --check-config commandline switch X-Git-Tag: auth-4.0.0-alpha2~21^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5efcfa63a5426b6c100ad8f41dcf356f3be59cc5;p=thirdparty%2Fpdns.git dnsdist: add --check-config commandline switch 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. --- diff --git a/docs/manpages/dnsdist.1.md b/docs/manpages/dnsdist.1.md index f24cd4dc5c..003e81c86c 100644 --- a/docs/manpages/dnsdist.1.md +++ b/docs/manpages/dnsdist.1.md @@ -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. diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index aa77c1483a..1aed77a37d 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1153,6 +1153,7 @@ struct { vector locals; vector 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 index 0000000000..3c2d1ed6b0 --- /dev/null +++ b/regression-tests.dnsdist/test_CheckConfig.py @@ -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)