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