]> git.ipfire.org Git - thirdparty/pdns.git/blob - tasks.py
Cleanup calidns.cc #ifdef
[thirdparty/pdns.git] / tasks.py
1 from invoke import task
2 from invoke.exceptions import Failure, UnexpectedExit
3
4 import os
5 import sys
6 import time
7
8 auth_backend_ip_addr = os.getenv('AUTH_BACKEND_IP_ADDR', '127.0.0.1')
9
10 clang_version = os.getenv('CLANG_VERSION', '13')
11 quiche_version = '0.18.0'
12 quiche_hash = 'eb242a14c4d801a90b57b6021dd29f7a62099f3a4d7a7ba889e105f8328e6c1f'
13
14 all_build_deps = [
15 'ccache',
16 'libboost-all-dev',
17 'libluajit-5.1-dev',
18 'libsodium-dev',
19 'libssl-dev',
20 'libsystemd-dev',
21 'libtool',
22 'make',
23 'pkg-config',
24 'python3-venv',
25 'systemd',
26 ]
27 git_build_deps = [
28 'autoconf',
29 'automake',
30 'bison',
31 'bzip2',
32 'curl',
33 'flex',
34 'git',
35 'ragel'
36 ]
37 auth_build_deps = [ # FIXME: perhaps we should be stealing these from the debian (Ubuntu) control file
38 'default-libmysqlclient-dev',
39 'libcdb-dev',
40 'libcurl4-openssl-dev',
41 'libgeoip-dev',
42 'libkrb5-dev',
43 'libldap2-dev',
44 'liblmdb-dev',
45 'libmaxminddb-dev',
46 'libp11-kit-dev',
47 'libpq-dev',
48 'libsqlite3-dev',
49 'libyaml-cpp-dev',
50 'libzmq3-dev',
51 'ruby-bundler',
52 'ruby-dev',
53 'sqlite3',
54 'unixodbc-dev',
55 'cmake',
56 ]
57 rec_build_deps = [
58 'libcap-dev',
59 'libfstrm-dev',
60 'libsnmp-dev',
61 ]
62 rec_bulk_deps = [
63 'curl',
64 'libboost-all-dev',
65 'libcap2',
66 'libfstrm0',
67 'libluajit-5.1-2',
68 '"libsnmp[1-9]+"',
69 'libsodium23',
70 'libssl1.1',
71 'libsystemd0',
72 'moreutils',
73 'pdns-tools',
74 'unzip',
75 ]
76 dnsdist_build_deps = [
77 'libcap-dev',
78 'libcdb-dev',
79 'libedit-dev',
80 'libfstrm-dev',
81 'libgnutls28-dev',
82 'libh2o-evloop-dev',
83 'liblmdb-dev',
84 'libnghttp2-dev',
85 'libre2-dev',
86 'libsnmp-dev',
87 ]
88 auth_test_deps = [ # FIXME: we should be generating some of these from shlibdeps in build
89 'authbind',
90 'bc',
91 'bind9utils',
92 'curl',
93 'default-jre-headless',
94 'dnsutils',
95 'faketime',
96 'gawk',
97 'krb5-user',
98 'ldnsutils',
99 '"libboost-serialization1.7[1-9]+"',
100 'libcdb1',
101 'libcurl4',
102 'libgeoip1',
103 'libkrb5-3',
104 'libldap-2.4-2',
105 'liblmdb0',
106 'libluajit-5.1-2',
107 'libmaxminddb0',
108 'libnet-dns-perl',
109 'libp11-kit0',
110 'libpq5',
111 'libsodium23',
112 'libsqlite3-dev',
113 'libssl1.1',
114 'libsystemd0',
115 'libyaml-cpp0.6',
116 'libzmq3-dev',
117 'lmdb-utils',
118 'prometheus',
119 'ruby-bundler',
120 'ruby-dev',
121 'socat',
122 'softhsm2',
123 'unbound-host',
124 'unixodbc',
125 'wget',
126 ]
127 doc_deps = [
128 'autoconf',
129 'automake',
130 'bison',
131 'curl',
132 'flex',
133 'g++',
134 'git',
135 'latexmk',
136 'libboost-all-dev',
137 'libedit-dev',
138 'libluajit-5.1-dev',
139 'libssl-dev',
140 'make',
141 'pkg-config',
142 'python3-venv',
143 'ragel',
144 'rsync',
145 ]
146 doc_deps_pdf = [
147 'texlive-binaries',
148 'texlive-formats-extra',
149 'texlive-latex-extra',
150 ]
151
152 @task
153 def apt_fresh(c):
154 c.sudo('apt-get update')
155 c.sudo('apt-get -y --allow-downgrades dist-upgrade')
156
157 @task
158 def install_clang(c):
159 """
160 install clang and llvm
161 """
162 c.sudo(f'apt-get -y --no-install-recommends install clang-{clang_version} llvm-{clang_version}')
163
164 @task
165 def install_clang_tidy_tools(c):
166 c.sudo(f'apt-get -y --no-install-recommends install clang-tidy-{clang_version} clang-tools-{clang_version} bear python3-yaml')
167
168 @task
169 def install_clang_runtime(c):
170 # this gives us the symbolizer, for symbols in asan/ubsan traces
171 c.sudo(f'apt-get -y --no-install-recommends install clang-{clang_version}')
172
173 @task
174 def ci_install_rust(c, repo):
175 c.sudo(f'{repo}/builder-support/helpers/install_rust.sh')
176
177 def install_libdecaf(c, product):
178 c.run('git clone https://git.code.sf.net/p/ed448goldilocks/code /tmp/libdecaf')
179 with c.cd('/tmp/libdecaf'):
180 c.run('git checkout 41f349')
181 c.run(f'CC={get_c_compiler()} CXX={get_cxx_compiler()} '
182 'cmake -B build '
183 '-DCMAKE_INSTALL_PREFIX=/usr/local '
184 '-DCMAKE_INSTALL_LIBDIR=lib '
185 '-DENABLE_STATIC=OFF '
186 '-DENABLE_TESTS=OFF '
187 '-DCMAKE_C_FLAGS="-Wno-sizeof-array-div -Wno-array-parameter" .')
188 c.run('make -C build')
189 c.run('sudo make -C build install')
190 c.sudo(f'mkdir -p /opt/{product}/libdecaf')
191 c.sudo(f'cp /usr/local/lib/libdecaf.so* /opt/{product}/libdecaf/.')
192
193 @task
194 def install_doc_deps(c):
195 c.sudo('apt-get install -y ' + ' '.join(doc_deps))
196
197 @task
198 def install_doc_deps_pdf(c):
199 c.sudo('apt-get install -y ' + ' '.join(doc_deps_pdf))
200
201 @task
202 def install_auth_build_deps(c):
203 c.sudo('apt-get install -y --no-install-recommends ' + ' '.join(all_build_deps + git_build_deps + auth_build_deps))
204 if os.getenv('DECAF_SUPPORT', 'no') == 'yes':
205 install_libdecaf(c, 'pdns-auth')
206
207 def is_coverage_enabled():
208 sanitizers = os.getenv('SANITIZERS')
209 if sanitizers:
210 sanitizers = sanitizers.split('+')
211 if 'tsan' in sanitizers:
212 return False
213 return os.getenv('COVERAGE') == 'yes'
214
215 def get_coverage():
216 return '--enable-coverage=clang' if is_coverage_enabled() else ''
217
218 @task
219 def install_coverage_deps(c):
220 if is_coverage_enabled():
221 c.sudo(f'apt-get install -y --no-install-recommends llvm-{clang_version}')
222
223 @task
224 def generate_coverage_info(c, binary, outputDir):
225 if is_coverage_enabled():
226 version = os.getenv('BUILDER_VERSION')
227 c.run(f'llvm-profdata-{clang_version} merge -sparse -o {outputDir}/temp.profdata /tmp/code-*.profraw')
228 c.run(f'llvm-cov-{clang_version} export --format=lcov --ignore-filename-regex=\'^/usr/\' -instr-profile={outputDir}/temp.profdata -object {binary} > {outputDir}/coverage.lcov')
229 c.run(f'{outputDir}/.github/scripts/normalize_paths_in_coverage.py {outputDir} {version} {outputDir}/coverage.lcov {outputDir}/normalized_coverage.lcov')
230 c.run(f'mv {outputDir}/normalized_coverage.lcov {outputDir}/coverage.lcov')
231
232 def setup_authbind(c):
233 c.sudo('touch /etc/authbind/byport/53')
234 c.sudo('chmod 755 /etc/authbind/byport/53')
235
236 auth_backend_test_deps = dict(
237 gsqlite3=['sqlite3'],
238 gmysql=['default-libmysqlclient-dev'],
239 gpgsql=['libpq-dev'],
240 lmdb=[],
241 remote=[],
242 bind=[],
243 geoip=[],
244 lua2=[],
245 tinydns=[],
246 authpy=[],
247 godbc_sqlite3=['libsqliteodbc'],
248 godbc_mssql=['freetds-bin','tdsodbc'],
249 ldap=[],
250 geoip_mmdb=[]
251 )
252
253 @task(help={'backend': 'Backend to install test deps for, e.g. gsqlite3; can be repeated'}, iterable=['backend'], optional=['backend'])
254 def install_auth_test_deps(c, backend): # FIXME: rename this, we do way more than apt-get
255 extra=[]
256 for b in backend:
257 extra.extend(auth_backend_test_deps[b])
258 c.sudo('DEBIAN_FRONTEND=noninteractive apt-get -y install ' + ' '.join(extra+auth_test_deps))
259
260 c.run('chmod +x /opt/pdns-auth/bin/* /opt/pdns-auth/sbin/*')
261 # c.run('''if [ ! -e $HOME/bin/jdnssec-verifyzone ]; then
262 # wget https://github.com/dblacka/jdnssec-tools/releases/download/0.14/jdnssec-tools-0.14.tar.gz
263 # tar xfz jdnssec-tools-0.14.tar.gz -C $HOME
264 # rm jdnssec-tools-0.14.tar.gz
265 # fi
266 # echo 'export PATH=$HOME/jdnssec-tools-0.14/bin:$PATH' >> $BASH_ENV''') # FIXME: why did this fail with no error?
267 c.run('touch regression-tests/tests/verify-dnssec-zone/allow-missing regression-tests.nobackend/rectify-axfr/allow-missing') # FIXME: can this go?
268 # FIXME we may want to start a background recursor here to make ALIAS tests more robust
269 setup_authbind(c)
270
271 if os.getenv('DECAF_SUPPORT', 'no') == 'yes':
272 # Copy libdecaf out
273 c.sudo('mkdir -p /usr/local/lib')
274 c.sudo('cp /opt/pdns-auth/libdecaf/libdecaf.so* /usr/local/lib/.')
275
276 @task
277 def install_rec_bulk_deps(c): # FIXME: rename this, we do way more than apt-get
278 c.sudo('apt-get --no-install-recommends -y install ' + ' '.join(rec_bulk_deps))
279 c.run('chmod +x /opt/pdns-recursor/bin/* /opt/pdns-recursor/sbin/*')
280
281 @task
282 def install_rec_test_deps(c): # FIXME: rename this, we do way more than apt-get
283 c.sudo('apt-get --no-install-recommends install -y ' + ' '.join(rec_bulk_deps) + ' \
284 pdns-server pdns-backend-bind daemontools \
285 jq libfaketime lua-posix lua-socket bc authbind \
286 python3-venv python3-dev default-libmysqlclient-dev libpq-dev \
287 protobuf-compiler snmpd prometheus')
288
289 c.run('chmod +x /opt/pdns-recursor/bin/* /opt/pdns-recursor/sbin/*')
290
291 setup_authbind(c)
292
293 c.run('sed "s/agentxperms 0700 0755 recursor/agentxperms 0777 0755/g" regression-tests.recursor-dnssec/snmpd.conf | sudo tee /etc/snmp/snmpd.conf')
294 c.sudo('/etc/init.d/snmpd restart')
295 time.sleep(5)
296 c.sudo('chmod 755 /var/agentx')
297
298 @task
299 def install_dnsdist_test_deps(c): # FIXME: rename this, we do way more than apt-get
300 c.sudo('apt-get install -y \
301 libluajit-5.1-2 \
302 libboost-all-dev \
303 libcap2 \
304 libcdb1 \
305 libcurl4-openssl-dev \
306 libfstrm0 \
307 libgnutls30 \
308 libh2o-evloop0.13 \
309 liblmdb0 \
310 libnghttp2-14 \
311 "libre2-[1-9]+" \
312 libssl-dev \
313 libsystemd0 \
314 libsodium23 \
315 lua-socket \
316 patch \
317 protobuf-compiler \
318 python3-venv snmpd prometheus')
319 c.run('sed "s/agentxperms 0700 0755 dnsdist/agentxperms 0777 0755/g" regression-tests.dnsdist/snmpd.conf | sudo tee /etc/snmp/snmpd.conf')
320 c.sudo('/etc/init.d/snmpd restart')
321 time.sleep(5)
322 c.sudo('chmod 755 /var/agentx')
323
324 @task
325 def install_rec_build_deps(c):
326 c.sudo('apt-get install -y --no-install-recommends ' + ' '.join(all_build_deps + git_build_deps + rec_build_deps))
327
328 @task
329 def install_dnsdist_build_deps(c):
330 c.sudo('apt-get install -y --no-install-recommends ' + ' '.join(all_build_deps + git_build_deps + dnsdist_build_deps))
331
332 @task
333 def ci_autoconf(c):
334 c.run('autoreconf -vfi')
335
336 @task
337 def ci_docs_rec_generate(c):
338 c.run('python3 generate.py')
339
340 @task
341 def ci_docs_build(c):
342 c.run('make -f Makefile.sphinx -C docs html')
343
344 @task
345 def ci_docs_build_pdf(c):
346 c.run('make -f Makefile.sphinx -C docs latexpdf')
347
348 @task
349 def ci_docs_upload_master(c, docs_host, pdf, username, product, directory=""):
350 rsync_cmd = " ".join([
351 "rsync",
352 "--checksum",
353 "--recursive",
354 "--verbose",
355 "--no-p",
356 "--chmod=g=rwX",
357 "--exclude '*~'",
358 ])
359 c.run(f"{rsync_cmd} --delete ./docs/_build/{product}-html-docs/ {username}@{docs_host}:{directory}")
360 c.run(f"{rsync_cmd} ./docs/_build/{product}-html-docs.tar.bz2 {username}@{docs_host}:{directory}/html-docs.tar.bz2")
361 c.run(f"{rsync_cmd} ./docs/_build/latex/{pdf} {username}@{docs_host}:{directory}")
362
363 @task
364 def ci_docs_add_ssh(c, ssh_key, host_key):
365 c.run('mkdir -m 700 -p ~/.ssh')
366 c.run(f'echo "{ssh_key}" > ~/.ssh/id_ed25519')
367 c.run('chmod 600 ~/.ssh/id_ed25519')
368 c.run(f'echo "{host_key}" > ~/.ssh/known_hosts')
369
370
371 def get_sanitizers():
372 sanitizers = os.getenv('SANITIZERS', '')
373 if sanitizers != '':
374 sanitizers = sanitizers.split('+')
375 sanitizers = ['--enable-' + sanitizer for sanitizer in sanitizers]
376 sanitizers = ' '.join(sanitizers)
377 return sanitizers
378
379 def get_unit_tests(auth=False):
380 if os.getenv('UNIT_TESTS') != 'yes':
381 return ''
382 return '--enable-unit-tests --enable-backend-unit-tests' if auth else '--enable-unit-tests'
383
384 def get_build_concurrency(default=8):
385 return os.getenv('CONCURRENCY', default)
386
387 def get_fuzzing_targets():
388 return '--enable-fuzz-targets' if os.getenv('FUZZING_TARGETS') == 'yes' else ''
389
390 def is_compiler_clang():
391 compiler = os.getenv('COMPILER', 'clang')
392 return compiler == 'clang'
393
394 def get_c_compiler():
395 return f'clang-{clang_version}' if is_compiler_clang() else 'gcc'
396
397 def get_cxx_compiler():
398 return f'clang++-{clang_version}' if is_compiler_clang() else 'g++'
399
400 def get_optimizations():
401 optimizations = os.getenv('OPTIMIZATIONS', 'yes')
402 return '-O1' if optimizations == 'yes' else '-O0'
403
404 def get_cflags():
405 return " ".join([
406 get_optimizations(),
407 "-Werror=vla",
408 "-Werror=shadow",
409 "-Wformat=2",
410 "-Werror=format-security",
411 "-Werror=string-plus-int" if is_compiler_clang() else '',
412 ])
413
414
415 def get_cxxflags():
416 return " ".join([
417 get_cflags(),
418 "-Wp,-D_GLIBCXX_ASSERTIONS",
419 ])
420
421
422 def get_base_configure_cmd(additional_c_flags='', additional_cxx_flags='', enable_systemd=True, enable_sodium=True):
423 cflags = " ".join([get_cflags(), additional_c_flags])
424 cxxflags = " ".join([get_cxxflags(), additional_cxx_flags])
425 return " ".join([
426 f'CFLAGS="{cflags}"',
427 f'CXXFLAGS="{cxxflags}"',
428 './configure',
429 f"CC='{get_c_compiler()}'",
430 f"CXX='{get_cxx_compiler()}'",
431 "--enable-option-checking=fatal",
432 "--enable-systemd" if enable_systemd else '',
433 "--with-libsodium" if enable_sodium else '',
434 "--enable-fortify-source=auto",
435 "--enable-auto-var-init=pattern",
436 get_coverage(),
437 get_sanitizers()
438 ])
439
440
441 @task
442 def ci_auth_configure(c):
443 unittests = get_unit_tests(True)
444 fuzz_targets = get_fuzzing_targets()
445 modules = " ".join([
446 "bind",
447 "geoip",
448 "gmysql",
449 "godbc",
450 "gpgsql",
451 "gsqlite3",
452 "ldap",
453 "lmdb",
454 "lua2",
455 "pipe",
456 "remote",
457 "tinydns",
458 ])
459 configure_cmd = " ".join([
460 get_base_configure_cmd(),
461 "LDFLAGS='-L/usr/local/lib -Wl,-rpath,/usr/local/lib'",
462 f"--with-modules='{modules}'",
463 "--enable-tools",
464 "--enable-dns-over-tls",
465 "--enable-experimental-pkcs11",
466 "--enable-experimental-gss-tsig",
467 "--enable-remotebackend-zeromq",
468 "--with-lmdb=/usr",
469 "--with-libdecaf" if os.getenv('DECAF_SUPPORT', 'no') == 'yes' else '',
470 "--prefix=/opt/pdns-auth",
471 "--enable-ixfrdist",
472 unittests,
473 fuzz_targets
474 ])
475 res = c.run(configure_cmd, warn=True)
476 if res.exited != 0:
477 c.run('cat config.log')
478 raise UnexpectedExit(res)
479
480
481 @task
482 def ci_rec_configure(c):
483 unittests = get_unit_tests()
484
485 configure_cmd = " ".join([
486 get_base_configure_cmd(),
487 "--enable-nod",
488 "--prefix=/opt/pdns-recursor",
489 "--with-lua=luajit",
490 "--with-libcap",
491 "--with-net-snmp",
492 "--enable-dns-over-tls",
493 unittests,
494 ])
495 res = c.run(configure_cmd, warn=True)
496 if res.exited != 0:
497 c.run('cat config.log')
498 raise UnexpectedExit(res)
499
500
501 @task
502 def ci_dnsdist_configure(c, features):
503 additional_flags = ''
504 if features == 'full':
505 features_set = '--enable-dnstap \
506 --enable-dnscrypt \
507 --enable-dns-over-tls \
508 --enable-dns-over-https \
509 --enable-dns-over-quic \
510 --enable-systemd \
511 --prefix=/opt/dnsdist \
512 --with-gnutls \
513 --with-h2o \
514 --with-libsodium \
515 --with-lua=luajit \
516 --with-libcap \
517 --with-net-snmp \
518 --with-nghttp2 \
519 --with-re2'
520 else:
521 features_set = '--disable-dnstap \
522 --disable-dnscrypt \
523 --disable-ipcipher \
524 --disable-systemd \
525 --without-cdb \
526 --without-ebpf \
527 --without-gnutls \
528 --without-h2o \
529 --without-libedit \
530 --without-libsodium \
531 --without-lmdb \
532 --without-net-snmp \
533 --without-nghttp2 \
534 --without-re2'
535 additional_flags = '-DDISABLE_COMPLETION \
536 -DDISABLE_DELAY_PIPE \
537 -DDISABLE_DYNBLOCKS \
538 -DDISABLE_PROMETHEUS \
539 -DDISABLE_PROTOBUF \
540 -DDISABLE_BUILTIN_HTML \
541 -DDISABLE_CARBON \
542 -DDISABLE_SECPOLL \
543 -DDISABLE_DEPRECATED_DYNBLOCK \
544 -DDISABLE_LUA_WEB_HANDLERS \
545 -DDISABLE_NON_FFI_DQ_BINDINGS \
546 -DDISABLE_POLICIES_BINDINGS \
547 -DDISABLE_PACKETCACHE_BINDINGS \
548 -DDISABLE_DOWNSTREAM_BINDINGS \
549 -DDISABLE_COMBO_ADDR_BINDINGS \
550 -DDISABLE_CLIENT_STATE_BINDINGS \
551 -DDISABLE_QPS_LIMITER_BINDINGS \
552 -DDISABLE_SUFFIX_MATCH_BINDINGS \
553 -DDISABLE_NETMASK_BINDINGS \
554 -DDISABLE_DNSNAME_BINDINGS \
555 -DDISABLE_DNSHEADER_BINDINGS \
556 -DDISABLE_RECVMMSG \
557 -DDISABLE_WEB_CACHE_MANAGEMENT \
558 -DDISABLE_WEB_CONFIG \
559 -DDISABLE_RULES_ALTERING_QUERIES \
560 -DDISABLE_ECS_ACTIONS \
561 -DDISABLE_TOP_N_BINDINGS \
562 -DDISABLE_OCSP_STAPLING \
563 -DDISABLE_HASHED_CREDENTIALS \
564 -DDISABLE_FALSE_SHARING_PADDING \
565 -DDISABLE_NPN'
566 unittests = get_unit_tests()
567 fuzztargets = get_fuzzing_targets()
568 tools = f'''AR=llvm-ar-{clang_version} RANLIB=llvm-ranlib-{clang_version}''' if is_compiler_clang() else ''
569 configure_cmd = " ".join([
570 tools,
571 get_base_configure_cmd(additional_c_flags='', additional_cxx_flags=additional_flags, enable_systemd=False, enable_sodium=False),
572 features_set,
573 unittests,
574 fuzztargets,
575 ' --enable-lto=thin',
576 '--prefix=/opt/dnsdist'
577 ])
578
579 res = c.run(configure_cmd, warn=True)
580 if res.exited != 0:
581 c.run('cat config.log')
582 raise UnexpectedExit(res)
583
584 @task
585 def ci_auth_make(c):
586 c.run(f'make -j{get_build_concurrency()} -k V=1')
587
588 @task
589 def ci_auth_make_bear(c):
590 c.run(f'bear --append -- make -j{get_build_concurrency()} -k V=1')
591
592 @task
593 def ci_rec_make(c):
594 c.run(f'make -j{get_build_concurrency()} -k V=1')
595
596 @task
597 def ci_rec_make_bear(c):
598 # Assumed to be running under ./pdns/recursordist/
599 c.run(f'bear --append -- make -j{get_build_concurrency()} -k V=1')
600
601 @task
602 def ci_dnsdist_make(c):
603 c.run(f'make -j{get_build_concurrency(4)} -k V=1')
604
605 @task
606 def ci_dnsdist_make_bear(c):
607 # Assumed to be running under ./pdns/dnsdistdist/
608 c.run(f'bear --append -- make -j{get_build_concurrency(4)} -k V=1')
609
610 @task
611 def ci_auth_install_remotebackend_test_deps(c):
612 with c.cd('modules/remotebackend'):
613 # c.run('bundle config set path vendor/bundle')
614 c.run('sudo ruby -S bundle install')
615 c.sudo('apt-get install -y socat')
616
617 @task
618 def ci_auth_run_unit_tests(c):
619 res = c.run('make check', warn=True)
620 if res.exited != 0:
621 c.run('cat pdns/test-suite.log', warn=True)
622 c.run('cat modules/remotebackend/test-suite.log', warn=True)
623 raise UnexpectedExit(res)
624
625 @task
626 def ci_rec_run_unit_tests(c):
627 res = c.run('make check', warn=True)
628 if res.exited != 0:
629 c.run('cat test-suite.log')
630 raise UnexpectedExit(res)
631
632 @task
633 def ci_dnsdist_run_unit_tests(c):
634 res = c.run('make check', warn=True)
635 if res.exited != 0:
636 c.run('cat test-suite.log')
637 raise UnexpectedExit(res)
638
639 @task
640 def ci_make_distdir(c):
641 res = c.run('make distdir')
642
643 @task
644 def ci_make_install(c):
645 res = c.run('make install') # FIXME: this builds auth docs - again
646
647 @task
648 def add_auth_repo(c, dist_name, dist_release_name, pdns_repo_version):
649 c.sudo('apt-get install -y curl gnupg2')
650 if pdns_repo_version == 'master':
651 c.sudo('curl -s -o /etc/apt/trusted.gpg.d/pdns-repo.asc https://repo.powerdns.com/CBC8B383-pub.asc')
652 else:
653 c.sudo('curl -s -o /etc/apt/trusted.gpg.d/pdns-repo.asc https://repo.powerdns.com/FD380FBB-pub.asc')
654 c.run(f"echo 'deb [arch=amd64] http://repo.powerdns.com/{dist_name} {dist_release_name}-auth-{pdns_repo_version} main' | sudo tee /etc/apt/sources.list.d/pdns.list")
655 c.run("echo 'Package: pdns-*' | sudo tee /etc/apt/preferences.d/pdns")
656 c.run("echo 'Pin: origin repo.powerdns.com' | sudo tee -a /etc/apt/preferences.d/pdns")
657 c.run("echo 'Pin-Priority: 600' | sudo tee -a /etc/apt/preferences.d/pdns")
658 c.sudo('apt-get update')
659
660 @task
661 def test_api(c, product, backend=''):
662 if product == 'recursor':
663 with c.cd('regression-tests.api'):
664 c.run(f'PDNSRECURSOR=/opt/pdns-recursor/sbin/pdns_recursor ./runtests recursor {backend}')
665 elif product == 'auth':
666 with c.cd('regression-tests.api'):
667 c.run(f'PDNSSERVER=/opt/pdns-auth/sbin/pdns_server PDNSUTIL=/opt/pdns-auth/bin/pdnsutil SDIG=/opt/pdns-auth/bin/sdig MYSQL_HOST={auth_backend_ip_addr} PGHOST={auth_backend_ip_addr} PGPORT=5432 ./runtests authoritative {backend}')
668 else:
669 raise Failure('unknown product')
670
671 backend_regress_tests = dict(
672 bind = [
673 'bind-both',
674 'bind-dnssec-both',
675 'bind-dnssec-nsec3-both',
676 'bind-dnssec-nsec3-optout-both',
677 'bind-dnssec-nsec3-narrow',
678 # FIXME 'bind-dnssec-pkcs11'
679 ],
680 geoip = [
681 'geoip',
682 'geoip-nsec3-narrow'
683 ],
684 lua2 = ['lua2', 'lua2-dnssec'],
685 tinydns = ['tinydns'],
686 remote = [
687 'remotebackend-pipe',
688 'remotebackend-unix',
689 'remotebackend-http',
690 'remotebackend-zeromq',
691 'remotebackend-pipe-dnssec',
692 'remotebackend-unix-dnssec',
693 'remotebackend-http-dnssec',
694 'remotebackend-zeromq-dnssec'
695 ],
696 lmdb = [
697 'lmdb-nodnssec-both',
698 'lmdb-both',
699 'lmdb-nsec3-both',
700 'lmdb-nsec3-optout-both',
701 'lmdb-nsec3-narrow'
702 ],
703 gmysql = [
704 'gmysql',
705 'gmysql-nodnssec-both',
706 'gmysql-nsec3-both',
707 'gmysql-nsec3-optout-both',
708 'gmysql-nsec3-narrow',
709 'gmysql_sp-both'
710 ],
711 gpgsql = [
712 'gpgsql',
713 'gpgsql-nodnssec-both',
714 'gpgsql-nsec3-both',
715 'gpgsql-nsec3-optout-both',
716 'gpgsql-nsec3-narrow',
717 'gpgsql_sp-both'
718 ],
719 gsqlite3 = [
720 'gsqlite3',
721 'gsqlite3-nodnssec-both',
722 'gsqlite3-nsec3-both',
723 'gsqlite3-nsec3-optout-both',
724 'gsqlite3-nsec3-narrow'
725 ],
726 godbc_sqlite3 = ['godbc_sqlite3-nodnssec'],
727 godbc_mssql = [
728 'godbc_mssql',
729 'godbc_mssql-nodnssec',
730 'godbc_mssql-nsec3',
731 'godbc_mssql-nsec3-optout',
732 'godbc_mssql-nsec3-narrow'
733 ],
734 ldap = [
735 'ldap-tree',
736 'ldap-simple',
737 'ldap-strict'
738 ],
739 geoip_mmdb = ['geoip'],
740 )
741
742 godbc_mssql_credentials = {"username": "sa", "password": "SAsa12%%"}
743
744 godbc_config = f'''
745 [pdns-mssql-docker]
746 Driver=FreeTDS
747 Trace=No
748 Server={auth_backend_ip_addr}
749 Port=1433
750 Database=pdns
751 TDS_Version=7.1
752
753 [pdns-mssql-docker-nodb]
754 Driver=FreeTDS
755 Trace=No
756 Server={auth_backend_ip_addr}
757 Port=1433
758 TDS_Version=7.1
759
760 [pdns-sqlite3-1]
761 Driver = SQLite3
762 Database = pdns.sqlite3
763
764 [pdns-sqlite3-2]
765 Driver = SQLite3
766 Database = pdns.sqlite32
767 '''
768
769 def setup_godbc_mssql(c):
770 with open(os.path.expanduser("~/.odbc.ini"), "a") as f:
771 f.write(godbc_config)
772 c.sudo('sh -c \'echo "Threading=1" | cat /usr/share/tdsodbc/odbcinst.ini - | tee -a /etc/odbcinst.ini\'')
773 c.sudo('sed -i "s/libtdsodbc.so/\/usr\/lib\/x86_64-linux-gnu\/odbc\/libtdsodbc.so/g" /etc/odbcinst.ini')
774 c.run(f'echo "create database pdns" | isql -v pdns-mssql-docker-nodb {godbc_mssql_credentials["username"]} {godbc_mssql_credentials["password"]}')
775 # FIXME: Skip 8bit-txt-unescaped test
776 c.run('touch ${PWD}/regression-tests/tests/8bit-txt-unescaped/skip')
777
778 def setup_godbc_sqlite3(c):
779 with open(os.path.expanduser("~/.odbc.ini"), "a") as f:
780 f.write(godbc_config)
781 c.sudo('sed -i "s/libsqlite3odbc.so/\/usr\/lib\/x86_64-linux-gnu\/odbc\/libsqlite3odbc.so/g" /etc/odbcinst.ini')
782
783 def setup_ldap_client(c):
784 c.sudo('DEBIAN_FRONTEND=noninteractive apt-get install -y ldap-utils')
785 c.sudo(f'sh -c \'echo "{auth_backend_ip_addr} ldapserver" | tee -a /etc/hosts\'')
786
787 @task
788 def test_auth_backend(c, backend):
789 pdns_auth_env_vars = f'PDNS=/opt/pdns-auth/sbin/pdns_server PDNS2=/opt/pdns-auth/sbin/pdns_server SDIG=/opt/pdns-auth/bin/sdig NOTIFY=/opt/pdns-auth/bin/pdns_notify NSEC3DIG=/opt/pdns-auth/bin/nsec3dig SAXFR=/opt/pdns-auth/bin/saxfr ZONE2SQL=/opt/pdns-auth/bin/zone2sql ZONE2LDAP=/opt/pdns-auth/bin/zone2ldap ZONE2JSON=/opt/pdns-auth/bin/zone2json PDNSUTIL=/opt/pdns-auth/bin/pdnsutil PDNSCONTROL=/opt/pdns-auth/bin/pdns_control PDNSSERVER=/opt/pdns-auth/sbin/pdns_server SDIG=/opt/pdns-auth/bin/sdig GMYSQLHOST={auth_backend_ip_addr} GMYSQL2HOST={auth_backend_ip_addr} MYSQL_HOST={auth_backend_ip_addr} PGHOST={auth_backend_ip_addr} PGPORT=5432'
790
791 if backend == 'remote':
792 ci_auth_install_remotebackend_test_deps(c)
793
794 if backend == 'authpy':
795 c.sudo(f'sh -c \'echo "{auth_backend_ip_addr} kerberos-server" | tee -a /etc/hosts\'')
796 with c.cd('regression-tests.auth-py'):
797 c.run(f'{pdns_auth_env_vars} WITHKERBEROS=YES ./runtests')
798 return
799
800 if backend == 'godbc_sqlite3':
801 setup_godbc_sqlite3(c)
802 with c.cd('regression-tests'):
803 for variant in backend_regress_tests[backend]:
804 c.run(f'{pdns_auth_env_vars} GODBC_SQLITE3_DSN=pdns-sqlite3-1 ./start-test-stop 5300 {variant}')
805 return
806
807 if backend == 'godbc_mssql':
808 setup_godbc_mssql(c)
809 with c.cd('regression-tests'):
810 for variant in backend_regress_tests[backend]:
811 c.run(f'{pdns_auth_env_vars} GODBC_MSSQL_PASSWORD={godbc_mssql_credentials["password"]} GODBC_MSSQL_USERNAME={godbc_mssql_credentials["username"]} GODBC_MSSQL_DSN=pdns-mssql-docker GODBC_MSSQL2_PASSWORD={godbc_mssql_credentials["password"]} GODBC_MSSQL2_USERNAME={godbc_mssql_credentials["username"]} GODBC_MSSQL2_DSN=pdns-mssql-docker ./start-test-stop 5300 {variant}')
812 return
813
814 if backend == 'ldap':
815 setup_ldap_client(c)
816
817 if backend == 'geoip_mmdb':
818 with c.cd('regression-tests'):
819 for variant in backend_regress_tests[backend]:
820 c.run(f'{pdns_auth_env_vars} geoipdatabase=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb ./start-test-stop 5300 {variant}')
821 return
822
823 with c.cd('regression-tests'):
824 if backend == 'lua2':
825 c.run('touch trustedkeys') # avoid silly error during cleanup
826 for variant in backend_regress_tests[backend]:
827 c.run(f'{pdns_auth_env_vars} ./start-test-stop 5300 {variant}')
828
829 if backend == 'gsqlite3':
830 if os.getenv('SKIP_IPV6_TESTS'):
831 pdns_auth_env_vars += ' context=noipv6'
832 with c.cd('regression-tests.nobackend'):
833 c.run(f'{pdns_auth_env_vars} ./runtests')
834 c.run('/opt/pdns-auth/bin/pdnsutil test-algorithms')
835 return
836
837 @task
838 def test_ixfrdist(c):
839 with c.cd('regression-tests.ixfrdist'):
840 c.run('IXFRDISTBIN=/opt/pdns-auth/bin/ixfrdist ./runtests')
841
842 @task
843 def test_dnsdist(c):
844 c.run('chmod +x /opt/dnsdist/bin/*')
845 c.run('ls -ald /var /var/agentx /var/agentx/master')
846 c.run('ls -al /var/agentx/master')
847 with c.cd('regression-tests.dnsdist'):
848 c.run('DNSDISTBIN=/opt/dnsdist/bin/dnsdist LD_LIBRARY_PATH=/opt/dnsdist/lib/ ./runtests')
849
850 @task
851 def test_regression_recursor(c):
852 c.run('/opt/pdns-recursor/sbin/pdns_recursor --version')
853 c.run('PDNSRECURSOR=/opt/pdns-recursor/sbin/pdns_recursor RECCONTROL=/opt/pdns-recursor/bin/rec_control ./build-scripts/test-recursor')
854
855 @task
856 def test_bulk_recursor(c, threads, mthreads, shards):
857 # We run an extremely small version of the bulk test, as GH does not seem to be able to handle the UDP load
858 with c.cd('regression-tests'):
859 c.run('curl -LO http://s3-us-west-1.amazonaws.com/umbrella-static/top-1m.csv.zip')
860 c.run('unzip top-1m.csv.zip -d .')
861 c.run('chmod +x /opt/pdns-recursor/bin/* /opt/pdns-recursor/sbin/*')
862 c.run(f'DNSBULKTEST=/usr/bin/dnsbulktest RECURSOR=/opt/pdns-recursor/sbin/pdns_recursor RECCONTROL=/opt/pdns-recursor/bin/rec_control THRESHOLD=95 TRACE=no ./recursor-test 5300 100 {threads} {mthreads} {shards}')
863
864 @task
865 def install_swagger_tools(c):
866 c.run('npm install -g api-spec-converter')
867
868 @task
869 def swagger_syntax_check(c):
870 c.run('api-spec-converter docs/http-api/swagger/authoritative-api-swagger.yaml -f swagger_2 -t openapi_3 -s json -c')
871
872 @task
873 def install_coverity_tools(c, project):
874 token = os.getenv('COVERITY_TOKEN')
875 c.run(f'curl -s https://scan.coverity.com/download/linux64 --data "token={token}&project={project}" | gunzip | sudo tar xvf /dev/stdin --strip-components=1 --no-same-owner -C /usr/local', hide=True)
876
877 @task
878 def coverity_clang_configure(c):
879 c.sudo(f'/usr/local/bin/cov-configure --template --comptype clangcc --compiler clang++-{clang_version}')
880
881 @task
882 def coverity_make(c):
883 c.run('/usr/local/bin/cov-build --dir cov-int make -j8 -k')
884
885 @task
886 def coverity_tarball(c, tarball):
887 c.run(f'tar caf {tarball} cov-int')
888
889 @task
890 def coverity_upload(c, email, project, tarball):
891 token = os.getenv('COVERITY_TOKEN')
892 c.run(f'curl --form token={token} \
893 --form email="{email}" \
894 --form file=@{tarball} \
895 --form version="$(./builder-support/gen-version)" \
896 --form description="master build" \
897 https://scan.coverity.com/builds?project={project}', hide=True)
898
899 @task
900 def ci_build_and_install_quiche(c):
901 # we have to pass -L because GitHub will do a redirect, sadly
902 c.run(f'curl -L -o quiche-{quiche_version}.tar.gz https://github.com/cloudflare/quiche/archive/{quiche_version}.tar.gz')
903 # Line below should echo two spaces between digest and name
904 c.run(f'echo {quiche_hash}" "quiche-{quiche_version}.tar.gz | sha256sum -c -')
905 c.run(f'tar xf quiche-{quiche_version}.tar.gz')
906 with c.cd(f'quiche-{quiche_version}'):
907 c.run('cargo build --release --no-default-features --features ffi,boringssl-boring-crate --package quiche')
908 # cannot use c.sudo() inside a cd() context, see https://github.com/pyinvoke/invoke/issues/687
909 c.run('sudo install -Dm644 quiche/include/quiche.h /usr/include')
910 c.run('sudo install -Dm644 target/release/libquiche.so /usr/lib')
911 c.run('install -D target/release/libquiche.so /opt/dnsdist/lib/libquiche.so')
912 c.run(f"""sudo install -Dm644 /dev/stdin /usr/lib/pkgconfig/quiche.pc <<PC
913 # quiche
914 Name: quiche
915 Description: quiche library
916 URL: https://github.com/cloudflare/quiche
917 Version: {quiche_version}
918 Libs: -lquiche
919 PC""")
920
921 # this is run always
922 def setup():
923 if '/usr/lib/ccache' not in os.environ['PATH']:
924 os.environ['PATH']='/usr/lib/ccache:'+os.environ['PATH']
925
926 setup()