]>
Commit | Line | Data |
---|---|---|
1a152698 CH |
1 | #!/usr/bin/env python |
2 | # | |
3 | # Shell-script style. | |
4 | ||
541bb91b | 5 | from __future__ import print_function |
1a152698 | 6 | import os |
a1e51a8a | 7 | import requests |
2e8f4675 | 8 | from requests.exceptions import HTTPError |
02945d9a | 9 | import shutil |
1a152698 CH |
10 | import subprocess |
11 | import sys | |
12 | import tempfile | |
a1e51a8a | 13 | import time |
1a152698 | 14 | |
7a0ea291 | 15 | try: |
16 | raw_input | |
17 | except NameError: | |
18 | raw_input = input | |
19 | ||
0bbd0a64 KM |
20 | MYSQL_DB='pdnsapi' |
21 | MYSQL_USER='root' | |
22 | MYSQL_HOST=os.environ.get('MYSQL_HOST', 'localhost') | |
23 | MYSQL_PASSWD='' | |
24 | ||
25 | PGSQL_DB='pdnsapi' | |
0bbd0a64 | 26 | |
1a152698 | 27 | SQLITE_DB = 'pdns.sqlite3' |
0bbd0a64 KM |
28 | |
29 | LMDB_DB = 'pdns.lmdb' | |
30 | ||
7992c698 CH |
31 | WEBPORT = 5556 |
32 | DNSPORT = 5300 | |
bbef8f04 | 33 | APIKEY = '1234567890abcdefghijklmnopq-key' |
c563cbe5 | 34 | WEBPASSWORD = 'something' |
c6c3c165 | 35 | PDNSUTIL_CMD = [os.environ.get("PDNSUTIL", "../pdns/pdnsutil"), "--config-dir=."] |
1a152698 | 36 | |
0bbd0a64 KM |
37 | ZONES = ["example.com", "powerdnssec.org", "cryptokeys.org"] |
38 | ZONE_DIR = "../regression-tests/zones/" | |
39 | ||
40 | AUTH_MYSQL_TPL = """ | |
41 | # Generated by runtests.py | |
42 | launch=gmysql | |
43 | gmysql-dnssec=on | |
44 | gmysql-dbname="""+MYSQL_DB+""" | |
45 | gmysql-user="""+MYSQL_USER+""" | |
46 | gmysql-host="""+MYSQL_HOST+""" | |
47 | gmysql-password="""+MYSQL_PASSWD+""" | |
48 | """ | |
49 | ||
50 | AUTH_PGSQL_TPL = """ | |
1a152698 | 51 | # Generated by runtests.py |
0bbd0a64 KM |
52 | launch=gpgsql |
53 | gpgsql-dnssec=on | |
54 | gpgsql-dbname="""+PGSQL_DB+""" | |
bc6f4e68 KM |
55 | # on conflict is available in pg 9.5 and up |
56 | gpgsql-set-tsig-key-query=insert into tsigkeys (name,algorithm,secret) values($1,$2,$3) on conflict(name, algorithm) do update set secret=Excluded.secret | |
ccfabd0d CH |
57 | """ |
58 | ||
0bbd0a64 | 59 | AUTH_SQLITE_TPL = """ |
ccfabd0d | 60 | # Generated by runtests.py |
0bbd0a64 | 61 | launch=gsqlite3 |
ccfabd0d CH |
62 | gsqlite3-dnssec=on |
63 | gsqlite3-database="""+SQLITE_DB+""" | |
0bbd0a64 KM |
64 | """ |
65 | ||
66 | AUTH_LMDB_TPL = """ | |
67 | # Generated by runtests.py | |
68 | launch=lmdb | |
69 | lmdb-filename="""+LMDB_DB+""" | |
70 | """ | |
71 | ||
72 | AUTH_COMMON_TPL = """ | |
ccfabd0d | 73 | module-dir=../regression-tests/modules |
1258fecd | 74 | default-soa-edit=INCEPTION-INCREMENT |
0bbd0a64 KM |
75 | launch+=bind |
76 | bind-config=bindbackend.conf | |
ef550199 | 77 | loglevel=5 |
a21e8566 CH |
78 | """ |
79 | ||
80 | BINDBACKEND_CONF_TPL = """ | |
81 | # Generated by runtests.py | |
1a152698 CH |
82 | """ |
83 | ||
41942bb3 CH |
84 | ACL_LIST_TPL = """ |
85 | # Generated by runtests.py | |
86 | # local host | |
87 | 127.0.0.1 | |
88 | ::1 | |
89 | """ | |
90 | ||
35189b7d KF |
91 | ACL_NOTIFY_LIST_TPL = """ |
92 | # Generated by runtests.py | |
93 | # local host | |
94 | 127.0.0.1 | |
95 | ::1 | |
96 | """ | |
97 | ||
02945d9a CH |
98 | REC_EXAMPLE_COM_CONF_TPL = """ |
99 | # Generated by runtests.py | |
57a954ff | 100 | auth-zones+=example.com=../regression-tests/zones/example.com.rec |
02945d9a CH |
101 | """ |
102 | ||
103 | REC_CONF_TPL = """ | |
104 | # Generated by runtests.py | |
105 | auth-zones= | |
106 | forward-zones= | |
107 | forward-zones-recurse= | |
2c4e6880 | 108 | allow-from-file=acl.list |
35189b7d | 109 | allow-notify-from-file=acl-notify.list |
d07bf7ff | 110 | api-config-dir=%(conf_dir)s |
02945d9a | 111 | include-dir=%(conf_dir)s |
6ab8d5ea | 112 | devonly-regression-test-mode |
02945d9a CH |
113 | """ |
114 | ||
c1374bdb | 115 | |
02945d9a CH |
116 | def ensure_empty_dir(name): |
117 | if os.path.exists(name): | |
118 | shutil.rmtree(name) | |
119 | os.mkdir(name) | |
120 | ||
121 | ||
7992c698 CH |
122 | def format_call_args(cmd): |
123 | return "$ '%s'" % ("' '".join(cmd)) | |
124 | ||
125 | ||
126 | def run_check_call(cmd, *args, **kwargs): | |
541bb91b | 127 | print(format_call_args(cmd)) |
7992c698 CH |
128 | subprocess.check_call(cmd, *args, **kwargs) |
129 | ||
130 | ||
5f8fa6d4 CH |
131 | wait = ('--wait' in sys.argv) |
132 | if wait: | |
133 | sys.argv.remove('--wait') | |
134 | ||
6754ef71 CH |
135 | tests = [opt for opt in sys.argv if opt.startswith('--tests=')] |
136 | if tests: | |
137 | for opt in tests: | |
138 | sys.argv.remove(opt) | |
139 | tests = [opt.split('=', 1)[1] for opt in tests] | |
140 | ||
0bbd0a64 KM |
141 | daemon = (len(sys.argv) >= 2) and sys.argv[1] or None |
142 | backend = (len(sys.argv) == 3) and sys.argv[2] or 'gsqlite3' | |
143 | ||
144 | if daemon not in ('authoritative', 'recursor') or backend not in ('gmysql', 'gpgsql', 'gsqlite3', 'lmdb'): | |
145 | print("Usage: ./runtests (authoritative|recursor) [gmysql|gpgsql|gsqlite3|lmdb]") | |
7c876c30 CH |
146 | sys.exit(2) |
147 | ||
148 | daemon = sys.argv[1] | |
149 | ||
7992c698 | 150 | pdns_server = os.environ.get("PDNSSERVER", "../pdns/pdns_server") |
bf6096f5 | 151 | pdns_recursor = os.environ.get("PDNSRECURSOR", "../pdns/recursordist/pdns_recursor") |
7992c698 CH |
152 | common_args = [ |
153 | "--daemon=no", "--socket-dir=.", "--config-dir=.", | |
154 | "--local-address=127.0.0.1", "--local-port="+str(DNSPORT), | |
c563cbe5 CH |
155 | "--webserver=yes", "--webserver-port="+str(WEBPORT), "--webserver-address=127.0.0.1", |
156 | "--webserver-password="+WEBPASSWORD, | |
7992c698 CH |
157 | "--api-key="+APIKEY |
158 | ] | |
bf6096f5 | 159 | |
0567c609 CH |
160 | # Take sdig if it exists (recursor in travis), otherwise build it from Authoritative source. |
161 | sdig = os.environ.get("SDIG", "") | |
162 | if sdig: | |
163 | sdig = os.path.abspath(sdig) | |
164 | if not sdig or not os.path.exists(sdig): | |
165 | run_check_call(["make", "-C", "../pdns", "sdig"]) | |
166 | sdig = "../pdns/sdig" | |
167 | ||
118d3b31 | 168 | |
7c876c30 | 169 | if daemon == 'authoritative': |
c6c3c165 | 170 | zone2sql = os.environ.get("ZONE2SQL", "../pdns/zone2sql") |
7c876c30 | 171 | |
0bbd0a64 KM |
172 | # Prepare mysql DB with some zones. |
173 | if backend == 'gmysql': | |
174 | subprocess.call(["mysqladmin", "--user=" + MYSQL_USER, "--password=" + MYSQL_PASSWD, "--host=" + MYSQL_HOST, "--force", "drop", MYSQL_DB]) | |
175 | ||
176 | run_check_call(["mysqladmin", "--user=" + MYSQL_USER, "--password=" + MYSQL_PASSWD, "--host=" + MYSQL_HOST, "create", MYSQL_DB]) | |
177 | ||
178 | with open('../modules/gmysqlbackend/schema.mysql.sql', 'r') as schema_file: | |
179 | run_check_call(["mysql", "--user=" + MYSQL_USER, "--password=" + MYSQL_PASSWD, "--host=" + MYSQL_HOST, MYSQL_DB], stdin=schema_file) | |
180 | ||
181 | with open('pdns.conf', 'w') as pdns_conf: | |
182 | pdns_conf.write(AUTH_MYSQL_TPL + AUTH_COMMON_TPL) | |
183 | ||
184 | # Prepare pgsql DB with some zones. | |
185 | elif backend == 'gpgsql': | |
5a8b492c | 186 | subprocess.call(["dropdb", PGSQL_DB]) |
0bbd0a64 | 187 | |
5a8b492c | 188 | subprocess.check_call(["createdb", PGSQL_DB]) |
0bbd0a64 KM |
189 | |
190 | with open('../modules/gpgsqlbackend/schema.pgsql.sql', 'r') as schema_file: | |
5a8b492c | 191 | subprocess.check_call(["psql", PGSQL_DB], stdin=schema_file) |
0bbd0a64 KM |
192 | |
193 | with open('pdns.conf', 'w') as pdns_conf: | |
194 | pdns_conf.write(AUTH_PGSQL_TPL + AUTH_COMMON_TPL) | |
195 | ||
ccfabd0d | 196 | # Prepare sqlite DB with some zones. |
0bbd0a64 KM |
197 | elif backend == 'gsqlite3': |
198 | subprocess.call("rm -f " + SQLITE_DB + "*", shell=True) | |
199 | ||
200 | with open('../modules/gsqlite3backend/schema.sqlite3.sql', 'r') as schema_file: | |
201 | run_check_call(["sqlite3", SQLITE_DB], stdin=schema_file) | |
202 | ||
203 | with open('pdns.conf', 'w') as pdns_conf: | |
204 | pdns_conf.write(AUTH_SQLITE_TPL + AUTH_COMMON_TPL) | |
205 | ||
206 | # Prepare lmdb DB with some zones. | |
207 | elif backend == 'lmdb': | |
208 | subprocess.call("rm -f " + LMDB_DB + "*", shell=True) | |
209 | ||
210 | with open('pdns.conf', 'w') as pdns_conf: | |
211 | pdns_conf.write(AUTH_LMDB_TPL + AUTH_COMMON_TPL) | |
7c876c30 | 212 | |
a21e8566 CH |
213 | with open('bindbackend.conf', 'w') as bindbackend_conf: |
214 | bindbackend_conf.write(BINDBACKEND_CONF_TPL) | |
215 | ||
0bbd0a64 KM |
216 | for zone in ZONES: |
217 | run_check_call(PDNSUTIL_CMD + ["load-zone", zone, ZONE_DIR+zone]) | |
ccfabd0d | 218 | |
7992c698 | 219 | run_check_call(PDNSUTIL_CMD + ["secure-zone", "powerdnssec.org"]) |
f5ad09dc | 220 | servercmd = [pdns_server] + common_args + ["--no-shuffle", "--dnsupdate=yes", "--cache-ttl=0", "--api=yes"] |
7c876c30 CH |
221 | |
222 | else: | |
02945d9a CH |
223 | conf_dir = 'rec-conf.d' |
224 | ensure_empty_dir(conf_dir) | |
41942bb3 CH |
225 | with open('acl.list', 'w') as acl_list: |
226 | acl_list.write(ACL_LIST_TPL) | |
35189b7d KF |
227 | with open('acl-notify.list', 'w') as acl_notify_list: |
228 | acl_notify_list.write(ACL_NOTIFY_LIST_TPL) | |
02945d9a CH |
229 | with open('recursor.conf', 'w') as recursor_conf: |
230 | recursor_conf.write(REC_CONF_TPL % locals()) | |
231 | with open(conf_dir+'/example.com..conf', 'w') as conf_file: | |
232 | conf_file.write(REC_EXAMPLE_COM_CONF_TPL) | |
7c876c30 | 233 | |
2c4e6880 | 234 | servercmd = [pdns_recursor] + common_args |
1a152698 CH |
235 | |
236 | ||
237 | # Now run pdns and the tests. | |
541bb91b CH |
238 | print("Launching server...") |
239 | print(format_call_args(servercmd)) | |
ab6031a1 | 240 | serverproc = subprocess.Popen(servercmd, close_fds=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
1a152698 | 241 | |
541bb91b | 242 | print("Waiting for webserver port to become available...") |
a1e51a8a | 243 | available = False |
ab6031a1 | 244 | time.sleep(1) |
a1e51a8a CH |
245 | for try_number in range(0, 10): |
246 | try: | |
247 | res = requests.get('http://127.0.0.1:%s/' % WEBPORT) | |
248 | available = True | |
249 | break | |
2e8f4675 O |
250 | except HTTPError as http_err: |
251 | print(f'HTTP error occurred: {http_err}') | |
252 | except Exception as err: | |
253 | print(f'Other error occurred: {err}') | |
ab6031a1 | 254 | time.sleep(1) |
a1e51a8a CH |
255 | |
256 | if not available: | |
541bb91b | 257 | print("Webserver port not reachable after 10 tries, giving up.") |
7992c698 CH |
258 | serverproc.terminate() |
259 | serverproc.wait() | |
ab6031a1 | 260 | print("==STDOUT===") |
02e8a66f | 261 | print(serverproc.stdout.read()) |
ab6031a1 | 262 | print("==STDERRR===") |
02e8a66f | 263 | print(serverproc.stderr.read()) |
a1e51a8a CH |
264 | sys.exit(2) |
265 | ||
541bb91b | 266 | print("Query for example.com/A to create statistic data...") |
0567c609 | 267 | run_check_call([sdig, "127.0.0.1", str(DNSPORT), "example.com", "A"]) |
118d3b31 | 268 | |
541bb91b | 269 | print("Running tests...") |
7992c698 | 270 | returncode = 0 |
1a152698 CH |
271 | test_env = {} |
272 | test_env.update(os.environ) | |
7cbc5255 | 273 | test_env.update({ |
c563cbe5 | 274 | 'WEBPASSWORD': WEBPASSWORD, |
7992c698 | 275 | 'WEBPORT': str(WEBPORT), |
7cbc5255 CH |
276 | 'APIKEY': APIKEY, |
277 | 'DAEMON': daemon, | |
0bbd0a64 KM |
278 | 'BACKEND': backend, |
279 | 'MYSQL_DB': MYSQL_DB, | |
280 | 'MYSQL_USER': MYSQL_USER, | |
281 | 'MYSQL_HOST': MYSQL_HOST, | |
282 | 'MYSQL_PASSWD': MYSQL_PASSWD, | |
283 | 'PGSQL_DB': PGSQL_DB, | |
7cbc5255 | 284 | 'SQLITE_DB': SQLITE_DB, |
0bbd0a64 | 285 | 'LMDB_DB': LMDB_DB, |
7cbc5255 | 286 | 'PDNSUTIL_CMD': ' '.join(PDNSUTIL_CMD), |
d19c22a1 CHB |
287 | 'SDIG': sdig, |
288 | 'DNSPORT': str(DNSPORT) | |
7cbc5255 | 289 | }) |
1a152698 CH |
290 | |
291 | try: | |
541bb91b | 292 | print("") |
db7b0230 | 293 | run_check_call(["pytest", "--junitxml=pytest.xml", "-v"] + tests, env=test_env) |
1a152698 | 294 | except subprocess.CalledProcessError as ex: |
7992c698 | 295 | returncode = ex.returncode |
1a152698 | 296 | finally: |
5f8fa6d4 | 297 | if wait: |
541bb91b | 298 | print("Waiting as requested, press ENTER to stop.") |
5f8fa6d4 | 299 | raw_input() |
7992c698 CH |
300 | serverproc.terminate() |
301 | serverproc.wait() | |
ab6031a1 O |
302 | print("==STDOUT===") |
303 | print(serverproc.stdout.read()) | |
304 | print("==STDERRR===") | |
305 | print(serverproc.stderr.read()) | |
1a152698 | 306 | |
7992c698 | 307 | sys.exit(returncode) |