From d73ede61f62e7f533588d2dddc71bd3608f5bb26 Mon Sep 17 00:00:00 2001 From: Tom Krizek Date: Tue, 7 Jun 2022 16:04:26 +0200 Subject: [PATCH 1/5] Remove trailing whitespace My editor doesn't like that! (cherry picked from commit 5d64d05be9ea9ff7587d6b15e51b01717e50505c) --- .gitlab-ci.yml | 2 +- doc/dev/style.md | 74 ++++++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0bda918f3a..5d3885745d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ variables: ASAN_SYMBOLIZER_PATH: /usr/lib/llvm-13/bin/llvm-symbolizer CLANG_FORMAT: clang-format-13 - CFLAGS_COMMON: -fno-omit-frame-pointer -fno-optimize-sibling-calls -O1 -g -Wall -Wextra + CFLAGS_COMMON: -fno-omit-frame-pointer -fno-optimize-sibling-calls -O1 -g -Wall -Wextra # Pass run-time flags to AddressSanitizer to get core dumps on error. ASAN_OPTIONS: abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1 diff --git a/doc/dev/style.md b/doc/dev/style.md index 64838c1fd1..3cc0a0aec5 100644 --- a/doc/dev/style.md +++ b/doc/dev/style.md @@ -78,7 +78,7 @@ conform well to BIND 9 C style: set showmode set autoindent set expandtab - + filetype plugin on let c_syntax_for_h = 1 autocmd FileType c,cc,cpp set cindent @@ -86,7 +86,7 @@ conform well to BIND 9 C style: autocmd FileType c,cc,cpp set fo=rotcq autocmd FileType c,cc,cpp set noexpandtab ts=8 autocmd FileType python set ts=4 sw=4 - + filetype indent on #### Vertical Whitespace @@ -136,7 +136,7 @@ Good: /* * Private variables. */ - + static int a /* Description of 'a'. */ static int b /* Description of 'b'. */ static char * c /* Description of 'c'. */ @@ -186,13 +186,13 @@ or for public files that do not declare any functions. * License, v. 2.0. If a copy of the MPL was not distributed with this * file, you can obtain one at https://mozilla.org/MPL/2.0/. */ - + #pragma once - + /***** ***** Module Info *****/ - + /* * (Module name here.) * @@ -216,20 +216,20 @@ or for public files that do not declare any functions. * Standards: * (Any standards relevant to the module are listed here.) */ - + /*** *** Imports ***/ - + /* #includes here. */ #include - + /*** *** Types ***/ - + /* (Type definitions here.) */ - + /*** *** Functions ***/ @@ -273,7 +273,7 @@ list is more than one line long: func1(int i) { /* whatever */ } - + int func2(int first_argument, int next_argument, int last_argument) @@ -371,7 +371,7 @@ Good: os_result_t result; os_descriptor_t s; - + result = os_socket_create(AF_INET, SOCK_STREAM, 0, &s); if (result != OS_R_SUCCESS) { /* Do something about the error. */ @@ -381,7 +381,7 @@ Good: Not so good: int s; - + /* * Obviously using interfaces like socket() (below) is allowed * since otherwise you couldn't call operating system routines; the @@ -432,26 +432,26 @@ Good: /* Test if flag set. */ if ((flags & FOO) != 0) { - + } /* Test if flag clear. */ if ((flags & BAR) == 0) { - + } /* Test if both flags set. */ if ((flags & (FOO|BAR)) == (FOO|BAR)) { - + } Bad: /* Test if flag set. */ if (flags & FOO) { - + } /* Test if flag clear. */ if (! (flags & BAR)) { - + } #### Testing for Zero or Non-zero @@ -462,9 +462,9 @@ variables. Good: int i = 10; - + /* ... */ - + if (i != 0) { /* Do something. */ } @@ -472,9 +472,9 @@ Good: Bad: int i = 10; - + /* ... */ - + if (i) { /* Do something. */ } @@ -489,9 +489,9 @@ comparison; do not treat a pointer variable as if it were a boolean. Good: char *c = NULL; - + /* ... */ - + if (c != NULL) { /* Do something. */ } @@ -499,9 +499,9 @@ Good: Bad: char *c = NULL; - + /* ... */ - + if (c) { /* Do something. */ } @@ -562,9 +562,9 @@ structure which is itself going to be freed immediately. Good: char *text; - + /* text is initialized here. */ - + isc_mem_free(mctx, text); text = NULL; @@ -635,7 +635,7 @@ Good: int bar; int baz; }; - + struct example x = { .foo = -1 }; Bad: @@ -644,9 +644,9 @@ Bad: int bar; int baz; }; - + struct example x; - + x.foo = -1; x.bar = 0; x.baz = 0; @@ -657,9 +657,9 @@ Good: int bar; int baz; }; - + struct example *x = isc_mem_get(mctx, sizeof(*x)); - + *x = (struct example){ .foo = -1 }; Bad: @@ -668,9 +668,9 @@ Bad: int bar; int baz; }; - + struct example *x = isc_mem_get(mctx, sizeof(*x)); - + x->foo = -1; x->bar = 0; x->baz = 0; @@ -748,7 +748,7 @@ value of the format parameter: dns_zone_setfile(dns_zone_t *zone, const char *file) { return (dns_zone_setfile2(zone, file, dns_masterformat_text); } - + isc_result_t dns_zone_setfile2(dns_zone_t *zone, const char *file, dns_masterformat_t format) From 1af7372fc016239afb76f44f7a97ea25194e199b Mon Sep 17 00:00:00 2001 From: Tom Krizek Date: Tue, 7 Jun 2022 16:06:05 +0200 Subject: [PATCH 2/5] Enforce Python codestyle with black Black is an opinionated tool for auto-formatting Python code so we no longer have to worry about the codestyle. For the codestyle decisions and discussion, refer to the upstream documentation [1]. [1] https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html (cherry picked from commit 5d2b7cab08e9bce1b25fa24f78d4ec81c731ac8e) --- .gitlab-ci.yml | 13 +++++++++++++ doc/dev/style.md | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5d3885745d..4dfcfa2fff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -427,6 +427,19 @@ misc: expire_in: "1 day" when: on_failure +black: + <<: *precheck_job + needs: [] + script: + - black $(git ls-files '*.py') + - git diff > black.patch + - if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi + artifacts: + paths: + - black.patch + expire_in: "1 week" + when: on_failure + clang-format: <<: *precheck_job needs: [] diff --git a/doc/dev/style.md b/doc/dev/style.md index 3cc0a0aec5..f4b79c5af5 100644 --- a/doc/dev/style.md +++ b/doc/dev/style.md @@ -855,9 +855,9 @@ name server. However, BIND 9 may use it for its system test environment, and in some cases for generating source or documentation files which are then committed to to the git repository. -For Python coding, we abide by the Python style guidelines described -in [PEP8](http://www.python.org/dev/peps/pep-0008/), with a few -modifications: +For Python coding, we enforce a common codestyle using the tool +[black](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html) +There are also a few other requirements: * The `__init__()` method should always be the first one declared in a class definition, like so: From e4bb3c3637f98e952d506851a61edc1f3f07ecd7 Mon Sep 17 00:00:00 2001 From: Tom Krizek Date: Tue, 7 Jun 2022 16:27:23 +0200 Subject: [PATCH 3/5] Auto-format Python files with black This patch is strictly the result of: $ black $(git ls-files '*.py') There have been no manual changes. (cherry picked from commit c9cb8ae9eb27b12da21a77f9be18cdd9a393a0ed) --- bin/tests/convert-trs-to-junit.py | 4 +- .../system/addzone/tests_rndc_deadlock.py | 46 ++-- bin/tests/system/chain/ans4/ans.py | 203 ++++++++------ bin/tests/system/checkds/tests-checkds.py | 257 +++++++++++------- bin/tests/system/conftest.py | 12 +- bin/tests/system/cookie/ans9/ans.py | 127 +++++---- bin/tests/system/digdelv/ans8/ans.py | 46 ++-- bin/tests/system/dispatch/ans3/ans.py | 8 +- bin/tests/system/dispatch/tests-connreset.py | 5 +- bin/tests/system/dnssec/ans10/ans.py | 42 ++- bin/tests/system/dnstap/ydump.py | 2 +- bin/tests/system/doth/conftest.py | 17 +- bin/tests/system/doth/get_openssl_version.py | 1 + bin/tests/system/doth/stress_http_quota.py | 53 ++-- bin/tests/system/doth/tests_gnutls.py | 47 ++-- bin/tests/system/forward/ans11/ans.py | 72 +++-- .../system/inline/tests_signed_zone_files.py | 32 +-- bin/tests/system/pipelined/ans5/ans.py | 74 +++-- bin/tests/system/pytest_custom_markers.py | 5 +- bin/tests/system/qmin/ans2/ans.py | 198 +++++++++++--- bin/tests/system/qmin/ans3/ans.py | 92 +++++-- bin/tests/system/qmin/ans4/ans.py | 127 +++++++-- .../rpzextra/tests-rpz-passthru-logging.py | 12 +- bin/tests/system/shutdown/tests-shutdown.py | 83 +++--- bin/tests/system/statschannel/generic.py | 20 +- .../system/statschannel/generic_dnspython.py | 30 +- bin/tests/system/statschannel/tests-json.py | 70 +++-- bin/tests/system/statschannel/tests-xml.py | 71 +++-- bin/tests/system/tcp/ans6/ans.py | 49 ++-- bin/tests/system/tcp/tests-tcp.py | 9 +- bin/tests/system/timeouts/tests-tcp.py | 71 +++-- bin/tests/system/wildcard/tests-wildcard.py | 38 +-- dangerfile.py | 225 ++++++++------- doc/arm/conf.py | 94 ++++--- doc/man/conf.py | 178 +++++++++--- util/parse_tsan.py | 8 +- 36 files changed, 1520 insertions(+), 908 deletions(-) diff --git a/bin/tests/convert-trs-to-junit.py b/bin/tests/convert-trs-to-junit.py index c94c0377ac..85b37dd629 100755 --- a/bin/tests/convert-trs-to-junit.py +++ b/bin/tests/convert-trs-to-junit.py @@ -76,9 +76,7 @@ def walk_trss(source_dir): # try to find dir/file path for a clickable link try: - t["rel_file_path"] = find_test_relative_path( - source_dir, test_name - ) + t["rel_file_path"] = find_test_relative_path(source_dir, test_name) except KeyError: pass # no existing path found diff --git a/bin/tests/system/addzone/tests_rndc_deadlock.py b/bin/tests/system/addzone/tests_rndc_deadlock.py index ec6ad1526b..bd21d62a90 100755 --- a/bin/tests/system/addzone/tests_rndc_deadlock.py +++ b/bin/tests/system/addzone/tests_rndc_deadlock.py @@ -16,61 +16,63 @@ import time def run_rndc(server, rndc_command): - ''' + """ Send the specified 'rndc_command' to 'server' with a timeout of 10 seconds - ''' - rndc = os.getenv('RNDC') - port = os.getenv('CONTROLPORT') + """ + rndc = os.getenv("RNDC") + port = os.getenv("CONTROLPORT") - cmdline = [rndc, '-c', '../common/rndc.conf', '-p', port, '-s', server] + cmdline = [rndc, "-c", "../common/rndc.conf", "-p", port, "-s", server] cmdline.extend(rndc_command) subprocess.check_output(cmdline, stderr=subprocess.STDOUT, timeout=10) def rndc_loop(test_state, domain): - ''' + """ Run "rndc addzone", "rndc modzone", and "rndc delzone" in a tight loop until the test is considered finished, ignoring errors - ''' + """ rndc_commands = [ - ['addzone', domain, - '{ type primary; file "example.db"; };'], - ['modzone', domain, - '{ type primary; file "example.db"; allow-transfer { any; }; };'], - ['delzone', domain], + ["addzone", domain, '{ type primary; file "example.db"; };'], + [ + "modzone", + domain, + '{ type primary; file "example.db"; allow-transfer { any; }; };', + ], + ["delzone", domain], ] - while not test_state['finished']: + while not test_state["finished"]: for command in rndc_commands: try: - run_rndc('10.53.0.3', command) + run_rndc("10.53.0.3", command) except subprocess.SubprocessError: pass def check_if_server_is_responsive(): - ''' + """ Check if server status can be successfully retrieved using "rndc status" - ''' + """ try: - run_rndc('10.53.0.3', ['status']) + run_rndc("10.53.0.3", ["status"]) return True except subprocess.SubprocessError: return False def test_rndc_deadlock(): - ''' + """ Test whether running "rndc addzone", "rndc modzone", and "rndc delzone" commands concurrently does not trigger a deadlock - ''' - test_state = {'finished': False} + """ + test_state = {"finished": False} # Create 4 worker threads running "rndc" commands in a loop. with concurrent.futures.ThreadPoolExecutor() as executor: for i in range(1, 5): - domain = 'example%d' % i + domain = "example%d" % i executor.submit(rndc_loop, test_state, domain) # Run "rndc status" 10 times, with 1-second pauses between attempts. @@ -84,7 +86,7 @@ def test_rndc_deadlock(): time.sleep(1) # Signal worker threads that the test is finished. - test_state['finished'] = True + test_state["finished"] = True # Check whether all "rndc status" commands succeeded. assert server_is_responsive diff --git a/bin/tests/system/chain/ans4/ans.py b/bin/tests/system/chain/ans4/ans.py index a5dad70edc..4d17705ef1 100755 --- a/bin/tests/system/chain/ans4/ans.py +++ b/bin/tests/system/chain/ans4/ans.py @@ -69,18 +69,22 @@ from dns.name import * ############################################################################ actions = [] rrs = [] + + def ctl_channel(msg): global actions, rrs msg = msg.splitlines().pop(0) - print ('received control message: %s' % msg) + print("received control message: %s" % msg) - msg = msg.split(b'|') + msg = msg.split(b"|") if len(msg) == 0: return - actions = [x.strip() for x in msg[0].split(b',')] - n = functools.reduce(lambda n, act: (n + (2 if act == b'dname' else 1)), [0] + actions) + actions = [x.strip() for x in msg[0].split(b",")] + n = functools.reduce( + lambda n, act: (n + (2 if act == b"dname" else 1)), [0] + actions + ) if len(msg) == 1: rrs = [] @@ -89,29 +93,30 @@ def ctl_channel(msg): rrs.append((i, b)) return - rlist = [x.strip() for x in msg[1].split(b',')] + rlist = [x.strip() for x in msg[1].split(b",")] rrs = [] for item in rlist: - if item[0] == b's'[0]: + if item[0] == b"s"[0]: i = int(item[1:].strip()) - 1 if i > n: - print ('invalid index %d' + (i + 1)) + print("invalid index %d" + (i + 1)) continue rrs.append((int(item[1:]) - 1, True)) else: i = int(item) - 1 if i > n: - print ('invalid index %d' % (i + 1)) + print("invalid index %d" % (i + 1)) continue rrs.append((i, False)) + ############################################################################ # Respond to a DNS query. ############################################################################ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() - labels = qname.lower().split('.') + labels = qname.lower().split(".") wantsigs = True if m.ednsflags & dns.flags.DO else False # get qtype @@ -124,27 +129,27 @@ def create_response(msg): # - sld is 'example' # - tld is 'com.' name = labels.pop(0) - domain = '.'.join(labels) + domain = ".".join(labels) sld = labels.pop(0) - tld = '.'.join(labels) + tld = ".".join(labels) - print ('query: ' + qname + '/' + typename) - print ('domain: ' + domain) + print("query: " + qname + "/" + typename) + print("domain: " + domain) # default answers, depending on QTYPE. # currently only A, AAAA, TXT and NS are supported. ttl = 86400 - additionalA = '10.53.0.4' - additionalAAAA = 'fd92:7065:b8e:ffff::4' - if typename == 'A': - final = '10.53.0.4' - elif typename == 'AAAA': - final = 'fd92:7065:b8e:ffff::4' - elif typename == 'TXT': - final = 'Some\ text\ here' - elif typename == 'NS': + additionalA = "10.53.0.4" + additionalAAAA = "fd92:7065:b8e:ffff::4" + if typename == "A": + final = "10.53.0.4" + elif typename == "AAAA": + final = "fd92:7065:b8e:ffff::4" + elif typename == "TXT": + final = "Some\ text\ here" + elif typename == "NS": domain = qname - final = ('ns1.%s' % domain) + final = "ns1.%s" % domain else: final = None @@ -153,9 +158,9 @@ def create_response(msg): delta = timedelta(30) t1 = t - delta t2 = t + delta - inception=t1.strftime('%Y%m%d000000') - expiry=t2.strftime('%Y%m%d000000') - sigdata='OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso=' + inception = t1.strftime("%Y%m%d000000") + expiry = t2.strftime("%Y%m%d000000") + sigdata = "OCXH2De0yE4NMTl9UykvOsJ4IBGs/ZIpff2rpaVJrVG7jQfmj50otBAp A0Zo7dpBU4ofv0N/F2Ar6LznCncIojkWptEJIAKA5tHegf/jY39arEpO cevbGp6DKxFhlkLXNcw7k9o7DSw14OaRmgAjXdTFbrl4AiAa0zAttFko Tso=" # construct answer set. answers = [] @@ -165,71 +170,97 @@ def create_response(msg): i = 0 for action in actions: - if name != 'test': + if name != "test": continue - if action == b'xname': - owner = curname + '.' + curdom - newname = 'cname%d' % i + if action == b"xname": + owner = curname + "." + curdom + newname = "cname%d" % i i += 1 - newdom = 'domain%d.%s' % (i, tld) + newdom = "domain%d.%s" % (i, tld) i += 1 - target = newname + '.' + newdom - print ('add external CNAME %s to %s' % (owner, target)) + target = newname + "." + newdom + print("add external CNAME %s to %s" % (owner, target)) answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) - rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add external RRISG(CNAME) %s to %s' % (owner, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add external RRISG(CNAME) %s to %s" % (owner, target)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) curname = newname curdom = newdom continue - if action == b'cname': - owner = curname + '.' + curdom - newname = 'cname%d' % i - target = newname + '.' + curdom + if action == b"cname": + owner = curname + "." + curdom + newname = "cname%d" % i + target = newname + "." + curdom i += 1 - print ('add CNAME %s to %s' % (owner, target)) + print("add CNAME %s to %s" % (owner, target)) answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) - rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add RRSIG(CNAME) %s to %s' % (owner, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add RRSIG(CNAME) %s to %s" % (owner, target)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) curname = newname continue - if action == b'dname': + if action == b"dname": owner = curdom - newdom = 'domain%d.%s' % (i, tld) + newdom = "domain%d.%s" % (i, tld) i += 1 - print ('add DNAME %s to %s' % (owner, newdom)) + print("add DNAME %s to %s" % (owner, newdom)) answers.append(dns.rrset.from_text(owner, ttl, IN, DNAME, newdom)) - rrsig = 'DNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add RRSIG(DNAME) %s to %s' % (owner, newdom)) + rrsig = "DNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add RRSIG(DNAME) %s to %s" % (owner, newdom)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) - owner = curname + '.' + curdom - target = curname + '.' + newdom - print ('add synthesized CNAME %s to %s' % (owner, target)) + owner = curname + "." + curdom + target = curname + "." + newdom + print("add synthesized CNAME %s to %s" % (owner, target)) answers.append(dns.rrset.from_text(owner, ttl, IN, CNAME, target)) - rrsig = 'CNAME 5 3 %d %s %s 12345 %s %s' % \ - (ttl, expiry, inception, domain, sigdata) - print ('add synthesized RRSIG(CNAME) %s to %s' % (owner, target)) + rrsig = "CNAME 5 3 %d %s %s 12345 %s %s" % ( + ttl, + expiry, + inception, + domain, + sigdata, + ) + print("add synthesized RRSIG(CNAME) %s to %s" % (owner, target)) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) curdom = newdom continue # now add the final answer - owner = curname + '.' + curdom + owner = curname + "." + curdom answers.append(dns.rrset.from_text(owner, ttl, IN, rrtype, final)) - rrsig = '%s 5 3 %d %s %s 12345 %s %s' % \ - (typename, ttl, expiry, inception, domain, sigdata) + rrsig = "%s 5 3 %d %s %s 12345 %s %s" % ( + typename, + ttl, + expiry, + inception, + domain, + sigdata, + ) sigs.append(dns.rrset.from_text(owner, ttl, IN, RRSIG, rrsig)) # prepare the response and convert to wire format r = dns.message.make_response(m) - if name != 'test': + if name != "test": r.answer.append(answers[-1]) if wantsigs: r.answer.append(sigs[-1]) @@ -242,24 +273,29 @@ def create_response(msg): else: r.answer.append(answers[i]) - if typename != 'NS': - r.authority.append(dns.rrset.from_text(domain, ttl, IN, "NS", - ("ns1.%s" % domain))) - r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400, - IN, A, additionalA)) - r.additional.append(dns.rrset.from_text(('ns1.%s' % domain), 86400, - IN, AAAA, additionalAAAA)) + if typename != "NS": + r.authority.append( + dns.rrset.from_text(domain, ttl, IN, "NS", ("ns1.%s" % domain)) + ) + r.additional.append( + dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, A, additionalA) + ) + r.additional.append( + dns.rrset.from_text(("ns1.%s" % domain), 86400, IN, AAAA, additionalAAAA) + ) r.flags |= dns.flags.AA r.use_edns() return r.to_wire() + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -270,11 +306,15 @@ def sigterm(signum, frame): ip4 = "10.53.0.4" ip6 = "fd92:7065:b8e:ffff::4" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 -try: ctrlport=int(os.environ['EXTRAPORT1']) -except: ctrlport=5300 +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -296,18 +336,18 @@ ctrl_socket.listen(5) signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Control channel on %s port %d" % (ip4, ctrlport)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Control channel on %s port %d" % (ip4, ctrlport)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket, ctrl_socket] @@ -328,7 +368,7 @@ while running: if s == ctrl_socket: # Handle control channel input conn, addr = s.accept() - print ("Control channel connected") + print("Control channel connected") while True: msg = conn.recv(65535) if not msg: @@ -336,8 +376,7 @@ while running: ctl_channel(msg) conn.close() if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6)) + print("Query received on %s" % (ip4 if s == query4_socket else ip6)) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/checkds/tests-checkds.py b/bin/tests/system/checkds/tests-checkds.py index 68b197c73e..56777fb3af 100755 --- a/bin/tests/system/checkds/tests-checkds.py +++ b/bin/tests/system/checkds/tests-checkds.py @@ -19,7 +19,7 @@ import time import pytest -pytest.importorskip('dns', minversion='2.0.0') +pytest.importorskip("dns", minversion="2.0.0") import dns.exception import dns.message import dns.name @@ -55,18 +55,22 @@ def has_signed_apex_nsec(zone, response): def do_query(server, qname, qtype, tcp=False): - query = dns.message.make_query(qname, qtype, use_edns=True, - want_dnssec=True) + query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) try: if tcp: - response = dns.query.tcp(query, server.nameservers[0], timeout=3, - port=server.port) + response = dns.query.tcp( + query, server.nameservers[0], timeout=3, port=server.port + ) else: - response = dns.query.udp(query, server.nameservers[0], timeout=3, - port=server.port) + response = dns.query.udp( + query, server.nameservers[0], timeout=3, port=server.port + ) except dns.exception.Timeout: - print("error: query timeout for query {} {} to {}".format( - qname, qtype, server.nameservers[0])) + print( + "error: query timeout for query {} {} to {}".format( + qname, qtype, server.nameservers[0] + ) + ) return None return response @@ -77,10 +81,10 @@ def verify_zone(zone, transfer): assert verify is not None filename = "{}out".format(zone) - with open(filename, 'w', encoding='utf-8') as file: + with open(filename, "w", encoding="utf-8") as file: for rr in transfer.answer: file.write(rr.to_text()) - file.write('\n') + file.write("\n") # dnssec-verify command with default arguments. verify_cmd = [verify, "-z", "-o", zone, filename] @@ -108,30 +112,39 @@ def read_statefile(server, zone): if response.rcode() == dns.rcode.NOERROR: # fetch key id from response. for rr in response.answer: - if rr.match(dns.name.from_text(zone), dns.rdataclass.IN, - dns.rdatatype.DS, dns.rdatatype.NONE): + if rr.match( + dns.name.from_text(zone), + dns.rdataclass.IN, + dns.rdatatype.DS, + dns.rdatatype.NONE, + ): if count == 0: keyid = list(dict(rr.items).items())[0][0].key_tag count += 1 if count != 1: - print("error: expected a single DS in response for {} from {}," - "got {}".format(zone, addr, count)) + print( + "error: expected a single DS in response for {} from {}," + "got {}".format(zone, addr, count) + ) return {} else: - print("error: {} response for {} DNSKEY from {}".format( - dns.rcode.to_text(response.rcode()), zone, addr)) + print( + "error: {} response for {} DNSKEY from {}".format( + dns.rcode.to_text(response.rcode()), zone, addr + ) + ) return {} filename = "ns9/K{}+013+{:05d}.state".format(zone, keyid) print("read state file {}".format(filename)) try: - with open(filename, 'r', encoding='utf-8') as file: + with open(filename, "r", encoding="utf-8") as file: for line in file: - if line.startswith(';'): + if line.startswith(";"): continue - key, val = line.strip().split(':', 1) + key, val = line.strip().split(":", 1) state[key.strip()] = val.strip() except FileNotFoundError: @@ -147,14 +160,17 @@ def zone_check(server, zone): # wait until zone is fully signed. signed = False for _ in range(10): - response = do_query(server, zone, 'NSEC') + response = do_query(server, zone, "NSEC") if not isinstance(response, dns.message.Message): print("error: no response for {} NSEC from {}".format(zone, addr)) elif response.rcode() == dns.rcode.NOERROR: signed = has_signed_apex_nsec(zone, response) else: - print("error: {} response for {} NSEC from {}".format( - dns.rcode.to_text(response.rcode()), zone, addr)) + print( + "error: {} response for {} NSEC from {}".format( + dns.rcode.to_text(response.rcode()), zone, addr + ) + ) if signed: break @@ -165,14 +181,17 @@ def zone_check(server, zone): # check if zone if DNSSEC valid. verified = False - transfer = do_query(server, zone, 'AXFR', tcp=True) + transfer = do_query(server, zone, "AXFR", tcp=True) if not isinstance(transfer, dns.message.Message): print("error: no response for {} AXFR from {}".format(zone, addr)) elif transfer.rcode() == dns.rcode.NOERROR: verified = verify_zone(zone, transfer) else: - print("error: {} response for {} AXFR from {}".format( - dns.rcode.to_text(transfer.rcode()), zone, addr)) + print( + "error: {} response for {} AXFR from {}".format( + dns.rcode.to_text(transfer.rcode()), zone, addr + ) + ) assert verified @@ -182,7 +201,7 @@ def keystate_check(server, zone, key): deny = False search = key - if key.startswith('!'): + if key.startswith("!"): deny = True search = key[1:] @@ -213,7 +232,7 @@ def wait_for_log(filename, log): print("read log file {}".format(filename)) try: - with open(filename, 'r', encoding='utf-8') as file: + with open(filename, "r", encoding="utf-8") as file: s = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) if s.find(bytes(log, "ascii")) != -1: found = True @@ -241,67 +260,89 @@ def test_checkds_dspublished(named_port): # DS correctly published in parent. zone_check(server, "dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") + wait_for_log( + "ns9/named.run", + "zone dspublished.checkds/IN (signed): checkds: " "DS response from 10.53.0.2", + ) keystate_check(parent, "dspublished.checkds.", "DSPublish") # DS correctly published in parent (reference to parental-agent). zone_check(server, "reference.checkds.") - wait_for_log("ns9/named.run", - "zone reference.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") + wait_for_log( + "ns9/named.run", + "zone reference.checkds/IN (signed): checkds: " "DS response from 10.53.0.2", + ) keystate_check(parent, "reference.checkds.", "DSPublish") # DS not published in parent. zone_check(server, "missing-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone missing-dspublished.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") + wait_for_log( + "ns9/named.run", + "zone missing-dspublished.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) keystate_check(parent, "missing-dspublished.checkds.", "!DSPublish") # Badly configured parent. zone_check(server, "bad-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone bad-dspublished.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad-dspublished.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad-dspublished.checkds.", "!DSPublish") # TBD: DS published in parent, but bogus signature. # DS correctly published in all parents. zone_check(server, "multiple-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone multiple-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone multiple-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.4") + wait_for_log( + "ns9/named.run", + "zone multiple-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone multiple-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) keystate_check(parent, "multiple-dspublished.checkds.", "DSPublish") # DS published in only one of multiple parents. zone_check(server, "incomplete-dspublished.checkds.") - wait_for_log("ns9/named.run", - "zone incomplete-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone incomplete-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.4") - wait_for_log("ns9/named.run", - "zone incomplete-dspublished.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) keystate_check(parent, "incomplete-dspublished.checkds.", "!DSPublish") # One of the parents is badly configured. - wait_for_log("ns9/named.run", - "zone bad2-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone bad2-dspublished.checkds/IN (signed): checkds: " - "DS response from 10.53.0.4") - wait_for_log("ns9/named.run", - "zone bad2-dspublished.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad2-dspublished.checkds.", "!DSPublish") # TBD: DS published in all parents, but one has bogus signature. @@ -323,60 +364,82 @@ def test_checkds_dswithdrawn(named_port): # DS correctly published in single parent. zone_check(server, "dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") + wait_for_log( + "ns9/named.run", + "zone dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) keystate_check(parent, "dswithdrawn.checkds.", "DSRemoved") # DS not withdrawn from parent. zone_check(server, "missing-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone missing-dswithdrawn.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") + wait_for_log( + "ns9/named.run", + "zone missing-dswithdrawn.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) keystate_check(parent, "missing-dswithdrawn.checkds.", "!DSRemoved") # Badly configured parent. zone_check(server, "bad-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone bad-dswithdrawn.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad-dswithdrawn.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad-dswithdrawn.checkds.", "!DSRemoved") # TBD: DS published in parent, but bogus signature. # DS correctly withdrawn from all parents. zone_check(server, "multiple-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") - wait_for_log("ns9/named.run", - "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.7") + wait_for_log( + "ns9/named.run", + "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) keystate_check(parent, "multiple-dswithdrawn.checkds.", "DSRemoved") # DS withdrawn from only one of multiple parents. zone_check(server, "incomplete-dswithdrawn.checkds.") - wait_for_log("ns9/named.run", - "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " - "DS response from 10.53.0.2") - wait_for_log("ns9/named.run", - "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") - wait_for_log("ns9/named.run", - "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.7") + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) keystate_check(parent, "incomplete-dswithdrawn.checkds.", "!DSRemoved") # One of the parents is badly configured. - wait_for_log("ns9/named.run", - "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.5") - wait_for_log("ns9/named.run", - "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " - "empty DS response from 10.53.0.7") - wait_for_log("ns9/named.run", - "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " - "bad DS response from 10.53.0.6") + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) keystate_check(parent, "bad2-dswithdrawn.checkds.", "!DSRemoved") # TBD: DS withdrawn from all parents, but one has bogus signature. diff --git a/bin/tests/system/conftest.py b/bin/tests/system/conftest.py index 2fd05add7d..8abf963926 100644 --- a/bin/tests/system/conftest.py +++ b/bin/tests/system/conftest.py @@ -16,16 +16,16 @@ import os import pytest -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def named_port(): - return int(os.environ.get('PORT', default=5300)) + return int(os.environ.get("PORT", default=5300)) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def named_tlsport(): - return int(os.environ.get('TLSPORT', default=8853)) + return int(os.environ.get("TLSPORT", default=8853)) -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def control_port(): - return int(os.environ.get('CONTROLPORT', default=9953)) + return int(os.environ.get("CONTROLPORT", default=9953)) diff --git a/bin/tests/system/cookie/ans9/ans.py b/bin/tests/system/cookie/ans9/ans.py index abc6d36ee2..550909466a 100644 --- a/bin/tests/system/cookie/ans9/ans.py +++ b/bin/tests/system/cookie/ans9/ans.py @@ -40,20 +40,17 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + # DNS 2.0 keyring specifies the algorithm try: - keyring = dns.tsigkeyring.from_text({ "foo" : { - "hmac-sha256", - "aaaaaaaaaaaa" - } , - "fake" : { - "hmac-sha256", - "aaaaaaaaaaaa" - } - }) + keyring = dns.tsigkeyring.from_text( + { + "foo": {"hmac-sha256", "aaaaaaaaaaaa"}, + "fake": {"hmac-sha256", "aaaaaaaaaaaa"}, + } + ) except: - keyring = dns.tsigkeyring.from_text({ "foo" : "aaaaaaaaaaaa", - "fake" : "aaaaaaaaaaaa" }) + keyring = dns.tsigkeyring.from_text({"foo": "aaaaaaaaaaaa", "fake": "aaaaaaaaaaaa"}) dopass2 = False @@ -81,7 +78,7 @@ def create_response(msg, tcp, first, ns10): m = dns.message.from_wire(msg, keyring=keyring) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") rrtype = m.question[0].rdtype typename = dns.rdatatype.to_text(rrtype) @@ -113,27 +110,31 @@ def create_response(msg, tcp, first, ns10): # Add a server cookie to the response if labels[0] != "nocookie": for o in m.options: - if o.otype == 10: # Use 10 instead of COOKIE - if first and labels[0] == "withtsig" and not tcp: - r.use_tsig(keyring = keyring, - keyname = dns.name.from_text("fake"), - algorithm = HMAC_SHA256) - elif labels[0] != "tcponly" or tcp: - cookie = o - if len(o.data) == 8: - cookie.data = o.data + o.data - else: - cookie.data = o.data - r.use_edns(options=[cookie]) + if o.otype == 10: # Use 10 instead of COOKIE + if first and labels[0] == "withtsig" and not tcp: + r.use_tsig( + keyring=keyring, + keyname=dns.name.from_text("fake"), + algorithm=HMAC_SHA256, + ) + elif labels[0] != "tcponly" or tcp: + cookie = o + if len(o.data) == 8: + cookie.data = o.data + o.data + else: + cookie.data = o.data + r.use_edns(options=[cookie]) r.flags |= dns.flags.AA return r + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -146,8 +147,10 @@ ip4_addr2 = "10.53.0.10" ip6_addr1 = "fd92:7065:b8e:ffff::9" ip6_addr2 = "fd92:7065:b8e:ffff::10" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_udp1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_udp1.bind((ip4_addr1, port)) @@ -195,24 +198,32 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Using DNS version %s" % dns.version.version) -print ("Listening on %s port %d" % (ip4_addr1, port)) -print ("Listening on %s port %d" % (ip4_addr2, port)) +print("Using DNS version %s" % dns.version.version) +print("Listening on %s port %d" % (ip4_addr1, port)) +print("Listening on %s port %d" % (ip4_addr2, port)) if havev6: - print ("Listening on %s port %d" % (ip6_addr1, port)) - print ("Listening on %s port %d" % (ip6_addr2, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6_addr1, port)) + print("Listening on %s port %d" % (ip6_addr2, port)) +print("Ctrl-c to quit") if havev6: - input = [query4_udp1, query6_udp1, query4_tcp1, query6_tcp1, - query4_udp2, query6_udp2, query4_tcp2, query6_tcp2] + input = [ + query4_udp1, + query6_udp1, + query4_tcp1, + query6_tcp1, + query4_udp2, + query6_udp2, + query4_tcp2, + query6_tcp2, + ] else: input = [query4_udp1, query4_tcp1, query4_udp2, query4_tcp2] @@ -228,14 +239,19 @@ while running: for s in inputready: ns10 = False - if s == query4_udp1 or s == query6_udp1 or \ - s == query4_udp2 or s == query6_udp2: + if s == query4_udp1 or s == query6_udp1 or s == query4_udp2 or s == query6_udp2: if s == query4_udp1 or s == query6_udp1: - print ("UDP Query received on %s" % - (ip4_addr1 if s == query4_udp1 else ip6_addr1), end=" ") + print( + "UDP Query received on %s" + % (ip4_addr1 if s == query4_udp1 else ip6_addr1), + end=" ", + ) if s == query4_udp2 or s == query6_udp2: - print ("UDP Query received on %s" % - (ip4_addr2 if s == query4_udp2 else ip6_addr2), end=" ") + print( + "UDP Query received on %s" + % (ip4_addr2 if s == query4_udp2 else ip6_addr2), + end=" ", + ) ns10 = True # Handle incoming queries msg = s.recvfrom(65535) @@ -244,31 +260,36 @@ while running: print(dns.rcode.to_text(rsp.rcode())) s.sendto(rsp.to_wire(), msg[1]) if dopass2: - print ("Sending second UDP response without TSIG", end=" ") + print("Sending second UDP response without TSIG", end=" ") rsp = create_response(msg[0], False, False, ns10) s.sendto(rsp.to_wire(), msg[1]) print(dns.rcode.to_text(rsp.rcode())) - if s == query4_tcp1 or s == query6_tcp1 or \ - s == query4_tcp2 or s == query6_tcp2: + if s == query4_tcp1 or s == query6_tcp1 or s == query4_tcp2 or s == query6_tcp2: try: (cs, _) = s.accept() if s == query4_tcp1 or s == query6_tcp1: - print ("TCP Query received on %s" % - (ip4_addr1 if s == query4_tcp1 else ip6_addr1), end=" ") + print( + "TCP Query received on %s" + % (ip4_addr1 if s == query4_tcp1 else ip6_addr1), + end=" ", + ) if s == query4_tcp2 or s == query6_tcp2: - print ("TCP Query received on %s" % - (ip4_addr2 if s == query4_tcp2 else ip6_addr2), end=" ") + print( + "TCP Query received on %s" + % (ip4_addr2 if s == query4_tcp2 else ip6_addr2), + end=" ", + ) ns10 = True # get TCP message length buf = cs.recv(2) - length = struct.unpack('>H', buf[:2])[0] + length = struct.unpack(">H", buf[:2])[0] # grep DNS message msg = cs.recv(length) rsp = create_response(msg, True, True, ns10) print(dns.rcode.to_text(rsp.rcode())) wire = rsp.to_wire() - cs.send(struct.pack('>H', len(wire))) + cs.send(struct.pack(">H", len(wire))) cs.send(wire) cs.close() except s.timeout: diff --git a/bin/tests/system/digdelv/ans8/ans.py b/bin/tests/system/digdelv/ans8/ans.py index 333b2f6044..3e18edc1cc 100644 --- a/bin/tests/system/digdelv/ans8/ans.py +++ b/bin/tests/system/digdelv/ans8/ans.py @@ -21,14 +21,15 @@ import dns, dns.message from dns.rcode import * modes = [ - b"silent", # Do not respond - b"close", # UDP: same as silent; TCP: also close the connection - b"servfail", # Always respond with SERVFAIL - b"unstable", # Constantly switch between "silent" and "servfail" + b"silent", # Do not respond + b"close", # UDP: same as silent; TCP: also close the connection + b"servfail", # Always respond with SERVFAIL + b"unstable", # Constantly switch between "silent" and "servfail" ] mode = modes[0] n = 0 + def ctrl_channel(msg): global modes, mode, n @@ -40,6 +41,7 @@ def ctrl_channel(msg): n = 0 print("New mode: %s" % str(mode)) + def create_servfail(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() @@ -54,19 +56,25 @@ def create_servfail(msg): r.set_rcode(SERVFAIL) return r + def sigterm(signum, frame): print("Shutting down now...") os.remove("ans.pid") running = False sys.exit(0) + ip4 = "10.53.0.8" -try: port=int(os.environ["PORT"]) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 -try: ctrlport=int(os.environ['EXTRAPORT1']) -except: ctrlport=5300 +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 query4_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_udp.bind((ip4, port)) @@ -85,14 +93,14 @@ signal.signal(signal.SIGTERM, sigterm) f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) -print ("Listening on %s port %d" % (ip4, ctrlport)) -print ("Ctrl-c to quit") +print("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, ctrlport)) +print("Ctrl-c to quit") input = [query4_udp, query4_tcp, ctrl4_tcp] @@ -113,7 +121,11 @@ while running: n = n + 1 print("UDP query received on %s" % ip4, end=" ") msg = s.recvfrom(65535) - if mode == b"silent" or mode == b"close" or (mode == b"unstable" and n % 2 == 1): + if ( + mode == b"silent" + or mode == b"close" + or (mode == b"unstable" and n % 2 == 1) + ): # Do not respond. print("NO RESPONSE (%s)" % str(mode)) continue @@ -125,7 +137,7 @@ while running: else: print("NO RESPONSE (can not create a response)") else: - raise(Exception("unsupported mode: %s" % mode)) + raise (Exception("unsupported mode: %s" % mode)) elif s == query4_tcp: n = n + 1 print("TCP query received on %s" % ip4, end=" ") @@ -151,7 +163,7 @@ while running: print("NO RESPONSE (can not read the message length)") conn.close() continue - length = struct.unpack('>H', msg[:2])[0] + length = struct.unpack(">H", msg[:2])[0] msg = conn.recv(length) if len(msg) != length: print("NO RESPONSE (can not read the message)") @@ -161,12 +173,12 @@ while running: if rsp: print(dns.rcode.to_text(rsp.rcode())) wire = rsp.to_wire() - conn.send(struct.pack('>H', len(wire))) + conn.send(struct.pack(">H", len(wire))) conn.send(wire) else: print("NO RESPONSE (can not create a response)") else: - raise(Exception("unsupported mode: %s" % mode)) + raise (Exception("unsupported mode: %s" % mode)) except socket.error as e: print("NO RESPONSE (error: %s)" % str(e)) if conn: diff --git a/bin/tests/system/dispatch/ans3/ans.py b/bin/tests/system/dispatch/ans3/ans.py index b57d73c005..4e4ebacb0b 100644 --- a/bin/tests/system/dispatch/ans3/ans.py +++ b/bin/tests/system/dispatch/ans3/ans.py @@ -32,7 +32,7 @@ def port(): def udp_listen(port): udp = socket.socket(type=socket.SOCK_DGRAM) - udp.bind(('10.53.0.3', port)) + udp.bind(("10.53.0.3", port)) return udp @@ -40,7 +40,7 @@ def udp_listen(port): def tcp_listen(port): tcp = socket.socket(type=socket.SOCK_STREAM) tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - tcp.bind(('10.53.0.3', port)) + tcp.bind(("10.53.0.3", port)) tcp.listen(100) return tcp @@ -62,12 +62,12 @@ def tcp_once(tcp): def sigterm(signum, frame): - os.remove('ans.pid') + os.remove("ans.pid") sys.exit(0) def write_pid(): - with open('ans.pid', 'w') as f: + with open("ans.pid", "w") as f: pid = os.getpid() f.write("{}".format(pid)) diff --git a/bin/tests/system/dispatch/tests-connreset.py b/bin/tests/system/dispatch/tests-connreset.py index 61758ffe6d..f74bfd719a 100644 --- a/bin/tests/system/dispatch/tests-connreset.py +++ b/bin/tests/system/dispatch/tests-connreset.py @@ -20,7 +20,8 @@ import dns.rcode def test_connreset(named_port): - msg = dns.message.make_query("sub.example.", "A", want_dnssec=True, - use_edns=0, payload=1232) + msg = dns.message.make_query( + "sub.example.", "A", want_dnssec=True, use_edns=0, payload=1232 + ) ans = dns.query.udp(msg, "10.53.0.2", timeout=10, port=named_port) assert ans.rcode() == dns.rcode.SERVFAIL diff --git a/bin/tests/system/dnssec/ans10/ans.py b/bin/tests/system/dnssec/ans10/ans.py index c738978503..c2f60e68e5 100644 --- a/bin/tests/system/dnssec/ans10/ans.py +++ b/bin/tests/system/dnssec/ans10/ans.py @@ -30,6 +30,7 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + ############################################################################ # Respond to a DNS query. # SOA gets a unsigned response. @@ -54,10 +55,16 @@ def create_response(msg): now = datetime.today() expire = now + timedelta(days=30) inception = now - timedelta(days=1) - rrsig = "A 13 2 60 " + expire.strftime("%Y%m%d%H%M%S") + " " + \ - inception.strftime("%Y%m%d%H%M%S") + " 12345 " + qname + \ - " gB+eISXAhSPZU2i/II0W9ZUhC2SCIrb94mlNvP5092WAeXxqN/vG43/1nmDl" + \ - "y2Qs7y5VCjSMOGn85bnaMoAc7w==" + rrsig = ( + "A 13 2 60 " + + expire.strftime("%Y%m%d%H%M%S") + + " " + + inception.strftime("%Y%m%d%H%M%S") + + " 12345 " + + qname + + " gB+eISXAhSPZU2i/II0W9ZUhC2SCIrb94mlNvP5092WAeXxqN/vG43/1nmDl" + + "y2Qs7y5VCjSMOGn85bnaMoAc7w==" + ) r.answer.append(dns.rrset.from_text(qname, 1, IN, A, "10.53.0.10")) r.answer.append(dns.rrset.from_text(qname, 1, IN, RRSIG, rrsig)) elif rrtype == NS: @@ -69,12 +76,14 @@ def create_response(msg): r.flags |= dns.flags.AA return r + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -85,8 +94,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.10" ip6 = "fd92:7065:b8e:ffff::10" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -102,17 +113,17 @@ except: havev6 = False signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -131,8 +142,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py index 43cd227996..ab7e3c9ada 100644 --- a/bin/tests/system/dnstap/ydump.py +++ b/bin/tests/system/dnstap/ydump.py @@ -22,7 +22,7 @@ import pprint DNSTAP_READ = sys.argv[1] DATAFILE = sys.argv[2] -ARGS = [DNSTAP_READ, '-y', DATAFILE] +ARGS = [DNSTAP_READ, "-y", DATAFILE] with subprocess.Popen(ARGS, stdout=subprocess.PIPE) as f: for y in yaml.load_all(f.stdout, Loader=yaml.SafeLoader): diff --git a/bin/tests/system/doth/conftest.py b/bin/tests/system/doth/conftest.py index 01c2071468..94392ccc0d 100644 --- a/bin/tests/system/doth/conftest.py +++ b/bin/tests/system/doth/conftest.py @@ -20,15 +20,18 @@ import pytest @pytest.fixture def gnutls_cli_executable(): # Ensure gnutls-cli is available. - executable = shutil.which('gnutls-cli') + executable = shutil.which("gnutls-cli") if not executable: - pytest.skip('gnutls-cli not found in PATH') + pytest.skip("gnutls-cli not found in PATH") # Ensure gnutls-cli supports the --logfile command-line option. - output = subprocess.run([executable, '--logfile=/dev/null'], - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - check=False).stdout - if b'illegal option' in output: - pytest.skip('gnutls-cli does not support the --logfile option') + output = subprocess.run( + [executable, "--logfile=/dev/null"], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=False, + ).stdout + if b"illegal option" in output: + pytest.skip("gnutls-cli does not support the --logfile option") return executable diff --git a/bin/tests/system/doth/get_openssl_version.py b/bin/tests/system/doth/get_openssl_version.py index 0aea9afa36..f1d6f4bf00 100755 --- a/bin/tests/system/doth/get_openssl_version.py +++ b/bin/tests/system/doth/get_openssl_version.py @@ -12,5 +12,6 @@ # information regarding copyright ownership. import ssl + version = ssl.OPENSSL_VERSION_INFO print(version[0], version[1], version[2]) diff --git a/bin/tests/system/doth/stress_http_quota.py b/bin/tests/system/doth/stress_http_quota.py index c3586b2485..12e29c858e 100755 --- a/bin/tests/system/doth/stress_http_quota.py +++ b/bin/tests/system/doth/stress_http_quota.py @@ -36,7 +36,7 @@ if rlimit_nofile[0] < 1024: # Introduce some random delay def jitter(): - time.sleep((500 + random.randint(0, 250))/1000000.0) + time.sleep((500 + random.randint(0, 250)) / 1000000.0) # A set of simple procedures to get the test's configuration options @@ -77,8 +77,9 @@ class TCPConnector: tries = CONNECT_TRIES while tries > 0: try: - sock = socket.create_connection(address=(self.host, self.port), - timeout=None) + sock = socket.create_connection( + address=(self.host, self.port), timeout=None + ) self.connections.append(sock) break except ConnectionResetError: @@ -137,9 +138,10 @@ class SubDIG: def run(self): # pylint: disable=consider-using-with - with open(os.devnull, 'w', encoding='utf-8') as devnull: - self.sub_process = subprocess.Popen(self.get_command(), shell=True, - stdout=devnull) + with open(os.devnull, "w", encoding="utf-8") as devnull: + self.sub_process = subprocess.Popen( + self.get_command(), shell=True, stdout=devnull + ) def wait(self, timeout=None): res = None @@ -158,13 +160,11 @@ class SubDIG: # A simple wrapper class which allows running multiple dig instances # and examining their statuses in one logical operation. class MultiDIG: - def __init__(self, numdigs, http_secure=None, - extra_args=None): + def __init__(self, numdigs, http_secure=None, extra_args=None): assert int(numdigs) > 0 digs = [] for _ in range(1, int(numdigs) + 1): - digs.append(SubDIG(http_secure=http_secure, - extra_args=extra_args)) + digs.append(SubDIG(http_secure=http_secure, extra_args=extra_args)) self.digs = digs assert len(self.digs) == int(numdigs) @@ -179,12 +179,11 @@ class MultiDIG: # status. Returns true or false. def wait_for_result(self, result): return reduce( - lambda a, b: ((a == result or a is True) and b == result), - self.wait()) + lambda a, b: ((a == result or a is True) and b == result), self.wait() + ) def alive(self): - return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), - self.digs)) + return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), self.digs)) def completed(self): total = 0 @@ -203,8 +202,7 @@ def run_test(http_secure=True): assert subdig.wait() == 0, "DIG was expected to succeed" # Let's create a lot of TCP connections to the server stress the # HTTP quota - connector = TCPConnector(get_http_host(), - get_http_port(http_secure=http_secure)) + connector = TCPConnector(get_http_host(), get_http_port(http_secure=http_secure)) # Let's make queries until the quota kicks in subdig = SubDIG(http_secure=http_secure, extra_args=query_args) subdig.run() @@ -218,25 +216,28 @@ def run_test(http_secure=True): # At this point quota has kicked in. Additionally, let's create a # bunch of dig processes all trying to make a query against the # server with exceeded quota - multidig = MultiDIG(MULTIDIG_INSTANCES, http_secure=http_secure, - extra_args=query_args) + multidig = MultiDIG( + MULTIDIG_INSTANCES, http_secure=http_secure, extra_args=query_args + ) multidig.run() # Wait for the dig instance to complete. Not a single instance has # a chance to complete successfully because of the exceeded quota - assert subdig.wait(timeout=5) is None,\ - "The single DIG instance has stopped prematurely" + assert ( + subdig.wait(timeout=5) is None + ), "The single DIG instance has stopped prematurely" assert subdig.alive(), "The single DIG instance is expected to be alive" - assert multidig.alive(), \ - ("The DIG instances from the set are all expected to " - "be alive, but {} of them have completed")\ - .format(multidig.completed()) + assert multidig.alive(), ( + "The DIG instances from the set are all expected to " + "be alive, but {} of them have completed" + ).format(multidig.completed()) # Let's close opened connections (in random order) to let all dig # processes to complete connector.disconnect_all() # Wait for all processes to complete successfully assert subdig.wait() == 0, "Single DIG instance failed" - assert multidig.wait_for_result(0) is True,\ - "One or more of DIG instances returned unexpected results" + assert ( + multidig.wait_for_result(0) is True + ), "One or more of DIG instances returned unexpected results" def main(): diff --git a/bin/tests/system/doth/tests_gnutls.py b/bin/tests/system/doth/tests_gnutls.py index ea86a961b2..5ddb708fd2 100644 --- a/bin/tests/system/doth/tests_gnutls.py +++ b/bin/tests/system/doth/tests_gnutls.py @@ -18,7 +18,7 @@ import time import pytest -pytest.importorskip('dns') +pytest.importorskip("dns") import dns.exception import dns.message import dns.name @@ -28,18 +28,28 @@ import dns.rdatatype def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): # Prepare the example/SOA query which will be sent over TLS. - query = dns.message.make_query('example.', dns.rdatatype.SOA) + query = dns.message.make_query("example.", dns.rdatatype.SOA) query_wire = query.to_wire() - query_with_length = struct.pack('>H', len(query_wire)) + query_wire + query_with_length = struct.pack(">H", len(query_wire)) + query_wire # Run gnutls-cli. - gnutls_cli_args = [gnutls_cli_executable, '--no-ca-verification', '-V', - '--no-ocsp', '--alpn=dot', '--logfile=gnutls-cli.log', - '--port=%d' % named_tlsport, '10.53.0.1'] - with open('gnutls-cli.err', 'wb') as gnutls_cli_stderr, \ - subprocess.Popen(gnutls_cli_args, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=gnutls_cli_stderr, - bufsize=0) as gnutls_cli: + gnutls_cli_args = [ + gnutls_cli_executable, + "--no-ca-verification", + "-V", + "--no-ocsp", + "--alpn=dot", + "--logfile=gnutls-cli.log", + "--port=%d" % named_tlsport, + "10.53.0.1", + ] + with open("gnutls-cli.err", "wb") as gnutls_cli_stderr, subprocess.Popen( + gnutls_cli_args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=gnutls_cli_stderr, + bufsize=0, + ) as gnutls_cli: # Send the example/SOA query to the standard input of gnutls-cli. Do # not close standard input yet because that causes gnutls-cli to close # the TLS connection immediately, preventing the response from being @@ -56,8 +66,8 @@ def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): selector = selectors.DefaultSelector() selector.register(gnutls_cli.stdout, selectors.EVENT_READ) deadline = time.time() + 10 - gnutls_cli_output = b'' - response = b'' + gnutls_cli_output = b"" + response = b"" while not response and not gnutls_cli.poll(): if not selector.select(timeout=deadline - time.time()): break @@ -80,16 +90,19 @@ def test_gnutls_cli_query(gnutls_cli_executable, named_tlsport): gnutls_cli.kill() # Store the response received for diagnostic purposes. - with open('gnutls-cli.out.bin', 'wb') as response_bin: + with open("gnutls-cli.out.bin", "wb") as response_bin: response_bin.write(gnutls_cli_output) if response: - with open('gnutls-cli.out.txt', 'w', encoding='utf-8') as response_txt: + with open("gnutls-cli.out.txt", "w", encoding="utf-8") as response_txt: response_txt.write(response.to_text()) # Check whether a response was received and whether it is sane. assert response assert query.id == response.id assert len(response.answer) == 1 - assert response.answer[0].match(dns.name.from_text('example.'), - dns.rdataclass.IN, dns.rdatatype.SOA, - dns.rdatatype.NONE) + assert response.answer[0].match( + dns.name.from_text("example."), + dns.rdataclass.IN, + dns.rdatatype.SOA, + dns.rdatatype.NONE, + ) diff --git a/bin/tests/system/forward/ans11/ans.py b/bin/tests/system/forward/ans11/ans.py index ae636d46be..95993813f8 100644 --- a/bin/tests/system/forward/ans11/ans.py +++ b/bin/tests/system/forward/ans11/ans.py @@ -31,11 +31,13 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + # Create a UDP listener -def udp_listen(ip, port, is_ipv6 = False): +def udp_listen(ip, port, is_ipv6=False): try: - udp = socket.socket(socket.AF_INET6 if is_ipv6 else socket.AF_INET, - socket.SOCK_DGRAM) + udp = socket.socket( + socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_DGRAM + ) try: udp.bind((ip, port)) except: @@ -49,11 +51,13 @@ def udp_listen(ip, port, is_ipv6 = False): return udp + # Create a TCP listener -def tcp_listen(ip, port, is_ipv6 = False): +def tcp_listen(ip, port, is_ipv6=False): try: - tcp = socket.socket(socket.AF_INET6 if is_ipv6 else socket.AF_INET, - socket.SOCK_STREAM) + tcp = socket.socket( + socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_STREAM + ) try: tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcp.bind((ip, port)) @@ -69,10 +73,13 @@ def tcp_listen(ip, port, is_ipv6 = False): return tcp + ############################################################################ # Control channel - send "1" or "0" to enable or disable the "silent" mode. ############################################################################ silent = False + + def ctrl_channel(msg): global silent @@ -83,14 +90,15 @@ def ctrl_channel(msg): return if silent: - if msg == b'0': + if msg == b"0": silent = False print("Silent mode was disabled") else: - if msg == b'1': + if msg == b"1": silent = True print("Silent mode was enabled") + ############################################################################ # Respond to a DNS query. ############################################################################ @@ -107,8 +115,8 @@ def create_response(msg): r = dns.message.make_response(m) r.set_rcode(NOERROR) if rrtype == A: - tld=qname.split('.')[-2] + '.' - ns="local." + tld + tld = qname.split(".")[-2] + "." + ns = "local." + tld r.answer.append(dns.rrset.from_text(qname, 300, IN, A, "10.53.0.11")) r.answer.append(dns.rrset.from_text(tld, 300, IN, NS, "local." + tld)) r.additional.append(dns.rrset.from_text(ns, 300, IN, A, "10.53.0.11")) @@ -121,12 +129,14 @@ def create_response(msg): r.flags |= dns.flags.AA return r + def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -137,11 +147,15 @@ def sigterm(signum, frame): ip4 = "10.53.0.11" ip6 = "fd92:7065:b8e:ffff::11" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 -try: ctrlport=int(os.environ['EXTRAPORT1']) -except: ctrlport=5300 +try: + ctrlport = int(os.environ["EXTRAPORT1"]) +except: + ctrlport = 5300 ctrl4_tcp = tcp_listen(ip4, ctrlport) query4_udp = udp_listen(ip4, port) @@ -153,19 +167,19 @@ havev6 = query6_udp is not None and query6_tcp is not None signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, ctrlport)) -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, ctrlport)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) + print("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") +print("Ctrl-c to quit") if havev6: input = [ctrl4_tcp, query4_udp, query6_udp, query4_tcp, query6_tcp] @@ -200,8 +214,9 @@ while running: if conn: conn.close() elif s == query4_tcp or s == query6_tcp: - print("TCP query received on %s" % - (ip4 if s == query4_tcp else ip6), end=" ") + print( + "TCP query received on %s" % (ip4 if s == query4_tcp else ip6), end=" " + ) conn = None try: # Handle incoming queries @@ -213,7 +228,7 @@ while running: print("NO RESPONSE (can not read the message length)") conn.close() continue - length = struct.unpack('>H', msg[:2])[0] + length = struct.unpack(">H", msg[:2])[0] msg = conn.recv(length) if len(msg) != length: print("NO RESPONSE (can not read the message)") @@ -223,7 +238,7 @@ while running: if rsp: print(dns.rcode.to_text(rsp.rcode())) wire = rsp.to_wire() - conn.send(struct.pack('>H', len(wire))) + conn.send(struct.pack(">H", len(wire))) conn.send(wire) else: print("NO RESPONSE (can not create a response)") @@ -237,8 +252,9 @@ while running: if conn: conn.close() elif s == query4_udp or s == query6_udp: - print("UDP query received on %s" % - (ip4 if s == query4_udp else ip6), end=" ") + print( + "UDP query received on %s" % (ip4 if s == query4_udp else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) if not silent: diff --git a/bin/tests/system/inline/tests_signed_zone_files.py b/bin/tests/system/inline/tests_signed_zone_files.py index 12ac675db5..06806eeb7d 100755 --- a/bin/tests/system/inline/tests_signed_zone_files.py +++ b/bin/tests/system/inline/tests_signed_zone_files.py @@ -14,29 +14,29 @@ import struct class RawFormatHeader(dict): - ''' + """ A dictionary of raw-format header fields read from a zone file. - ''' + """ fields = [ - 'format', - 'version', - 'dumptime', - 'flags', - 'sourceserial', - 'lastxfrin', + "format", + "version", + "dumptime", + "flags", + "sourceserial", + "lastxfrin", ] def __init__(self, file_name): - header = struct.Struct('>IIIIII') - with open(file_name, 'rb') as data: + header = struct.Struct(">IIIIII") + with open(file_name, "rb") as data: header_data = data.read(header.size) super().__init__(zip(self.fields, header.unpack_from(header_data))) def test_unsigned_serial_number(): - ''' + """ Check whether all signed zone files in the "ns8" subdirectory contain the serial number of the unsigned version of the zone in the raw-format header. The test assumes that all "*.signed" files in the "ns8" subdirectory are in @@ -51,18 +51,18 @@ def test_unsigned_serial_number(): - example[0-9][0-9].com.db.signed files are initially signed by dnssec-signzone while the others - by named. - ''' + """ zones_with_unsigned_serial_missing = [] - for signed_zone in sorted(glob.glob('ns8/*.signed')): + for signed_zone in sorted(glob.glob("ns8/*.signed")): raw_header = RawFormatHeader(signed_zone) # Ensure the unsigned serial number is placed where it is expected. - assert raw_header['format'] == 2 - assert raw_header['version'] == 1 + assert raw_header["format"] == 2 + assert raw_header["version"] == 1 # Check whether the header flags indicate that the unsigned serial # number is set and that the latter is indeed set. - if raw_header['flags'] & 0x02 == 0 or raw_header['sourceserial'] == 0: + if raw_header["flags"] & 0x02 == 0 or raw_header["sourceserial"] == 0: zones_with_unsigned_serial_missing.append(signed_zone) assert not zones_with_unsigned_serial_missing diff --git a/bin/tests/system/pipelined/ans5/ans.py b/bin/tests/system/pipelined/ans5/ans.py index 0a64033ecb..bac5ed35d8 100644 --- a/bin/tests/system/pipelined/ans5/ans.py +++ b/bin/tests/system/pipelined/ans5/ans.py @@ -47,25 +47,28 @@ import struct DELAY = 0.5 THREADS = [] + def log(msg): - print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg) + print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg) def sigterm(*_): - log('SIGTERM received, shutting down') + log("SIGTERM received, shutting down") for thread in THREADS: thread.close() thread.join() - os.remove('ans.pid') + os.remove("ans.pid") sys.exit(0) + class TCPDelayer(threading.Thread): - """ For a given TCP connection conn we open a connection to (ip, port), - and then we delay each incoming packet by DELAY by putting it in a - queue. - In the pipelined test TCP should not be used, but it's here for - completnes. + """For a given TCP connection conn we open a connection to (ip, port), + and then we delay each incoming packet by DELAY by putting it in a + queue. + In the pipelined test TCP should not be used, but it's here for + completnes. """ + def __init__(self, conn, ip, port): threading.Thread.__init__(self) self.conn = conn @@ -81,13 +84,15 @@ class TCPDelayer(threading.Thread): while self.running: curr_timeout = 0.5 try: - curr_timeout = self.queue[0][0]-time.time() + curr_timeout = self.queue[0][0] - time.time() except StopIteration: pass if curr_timeout > 0: if curr_timeout == 0: curr_timeout = 0.5 - rfds, _, _ = select.select([self.conn, self.cconn], [], [], curr_timeout) + rfds, _, _ = select.select( + [self.conn, self.cconn], [], [], curr_timeout + ) if self.conn in rfds: data = self.conn.recv(65535) if not data: @@ -99,17 +104,19 @@ class TCPDelayer(threading.Thread): return self.conn.send(data) try: - while self.queue[0][0]-time.time() < 0: + while self.queue[0][0] - time.time() < 0: _, data = self.queue.pop(0) self.cconn.send(data) except StopIteration: pass + class UDPDelayer(threading.Thread): - """ Every incoming UDP packet is put in a queue for DELAY time, then - it's sent to (ip, port). We remember the query id to send the - response we get to a proper source, responses are not delayed. + """Every incoming UDP packet is put in a queue for DELAY time, then + it's sent to (ip, port). We remember the query id to send the + response we get to a proper source, responses are not delayed. """ + def __init__(self, usock, ip, port): threading.Thread.__init__(self) self.sock = usock @@ -126,50 +133,56 @@ class UDPDelayer(threading.Thread): while self.running: curr_timeout = 0.5 if self.queue: - curr_timeout = self.queue[0][0]-time.time() + curr_timeout = self.queue[0][0] - time.time() if curr_timeout >= 0: if curr_timeout == 0: curr_timeout = 0.5 - rfds, _, _ = select.select([self.sock, self.csock], [], [], curr_timeout) + rfds, _, _ = select.select( + [self.sock, self.csock], [], [], curr_timeout + ) if self.sock in rfds: data, addr = self.sock.recvfrom(65535) if not data: return self.queue.append((time.time() + DELAY, data)) - qid = struct.unpack('>H', data[:2])[0] - log('Received a query from %s, queryid %d' % (str(addr), qid)) + qid = struct.unpack(">H", data[:2])[0] + log("Received a query from %s, queryid %d" % (str(addr), qid)) self.qid_mapping[qid] = addr if self.csock in rfds: data, addr = self.csock.recvfrom(65535) if not data: return - qid = struct.unpack('>H', data[:2])[0] + qid = struct.unpack(">H", data[:2])[0] dst = self.qid_mapping.get(qid) if dst is not None: self.sock.sendto(data, dst) - log('Received a response from %s, queryid %d, sending to %s' % (str(addr), qid, str(dst))) - while self.queue and self.queue[0][0]-time.time() < 0: + log( + "Received a response from %s, queryid %d, sending to %s" + % (str(addr), qid, str(dst)) + ) + while self.queue and self.queue[0][0] - time.time() < 0: _, data = self.queue.pop(0) - qid = struct.unpack('>H', data[:2])[0] - log('Sending a query to %s, queryid %d' % (str(self.dst), qid)) + qid = struct.unpack(">H", data[:2])[0] + log("Sending a query to %s, queryid %d" % (str(self.dst), qid)) self.csock.sendto(data, self.dst) + def main(): signal.signal(signal.SIGTERM, sigterm) signal.signal(signal.SIGINT, sigterm) - with open('ans.pid', 'w') as pidfile: + with open("ans.pid", "w") as pidfile: print(os.getpid(), file=pidfile) - listenip = '10.53.0.5' - serverip = '10.53.0.2' + listenip = "10.53.0.5" + serverip = "10.53.0.2" try: - port = int(os.environ['PORT']) + port = int(os.environ["PORT"]) except KeyError: port = 5300 - log('Listening on %s:%d' % (listenip, port)) + log("Listening on %s:%d" % (listenip, port)) usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -187,12 +200,13 @@ def main(): while True: try: (clientsock, _) = sock.accept() - log('Accepted connection from %s' % clientsock) + log("Accepted connection from %s" % clientsock) thread = TCPDelayer(clientsock, serverip, port) thread.start() THREADS.append(thread) except socket.timeout: pass -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/bin/tests/system/pytest_custom_markers.py b/bin/tests/system/pytest_custom_markers.py index 256fb7db8d..55b02f6c58 100644 --- a/bin/tests/system/pytest_custom_markers.py +++ b/bin/tests/system/pytest_custom_markers.py @@ -16,5 +16,6 @@ import os import pytest -long_test = pytest.mark.skipif(not os.environ.get('CI_ENABLE_ALL_TESTS'), - reason='CI_ENABLE_ALL_TESTS not set') +long_test = pytest.mark.skipif( + not os.environ.get("CI_ENABLE_ALL_TESTS"), reason="CI_ENABLE_ALL_TESTS not set" +) diff --git a/bin/tests/system/qmin/ans2/ans.py b/bin/tests/system/qmin/ans2/ans.py index 583b388768..1994ff35db 100755 --- a/bin/tests/system/qmin/ans2/ans.py +++ b/bin/tests/system/qmin/ans2/ans.py @@ -31,9 +31,11 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + def endswith(domain, labels): return domain.endswith("." + labels) or domain == labels + ############################################################################ # Respond to a DNS query. # For good. it serves: @@ -65,7 +67,7 @@ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") # get qtype rrtype = m.question[0].rdtype @@ -88,22 +90,61 @@ def create_response(msg): # Direct query - give direct answer if endswith(lqname, "8.2.6.0.1.0.0.2.ip6.arpa."): # Delegate to ns3 - r.authority.append(dns.rrset.from_text("8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns3.good.")) - r.additional.append(dns.rrset.from_text("ns3.good.", 60, IN, A, "10.53.0.3")) - elif lqname == "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa." and rrtype == PTR: + r.authority.append( + dns.rrset.from_text( + "8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns3.good." + ) + ) + r.additional.append( + dns.rrset.from_text("ns3.good.", 60, IN, A, "10.53.0.3") + ) + elif ( + lqname + == "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa." + and rrtype == PTR + ): # Direct query - give direct answer - r.answer.append(dns.rrset.from_text("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", 1, IN, PTR, "nee.com.")) + r.answer.append( + dns.rrset.from_text( + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", + 1, + IN, + PTR, + "nee.com.", + ) + ) r.flags |= dns.flags.AA elif lqname == "1.0.0.2.ip6.arpa." and rrtype == NS: # NS query at the apex - r.answer.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, NS, "ns2.good.")) + r.answer.append( + dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, NS, "ns2.good.") + ) r.flags |= dns.flags.AA - elif endswith("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", lqname): + elif endswith( + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.", + lqname, + ): # NODATA answer - r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "1.0.0.2.ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "1.0.0.2.ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) r.set_rcode(NXDOMAIN) return r elif endswith(lqname, "ip6.arpa."): @@ -113,35 +154,71 @@ def create_response(msg): r.flags |= dns.flags.AA elif endswith("1.0.0.2.ip6.arpa.", lqname): # NODATA answer - r.authority.append(dns.rrset.from_text("ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("ip6.arpa.", 30, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "ip6.arpa.", + 30, + IN, + SOA, + "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) r.set_rcode(NXDOMAIN) return r elif endswith(lqname, "stale."): if endswith(lqname, "a.b.stale."): # Delegate to ns.a.b.stale. - r.authority.append(dns.rrset.from_text("a.b.stale.", 2, IN, NS, "ns.a.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.a.b.stale.", 2, IN, A, "10.53.0.3")) + r.authority.append( + dns.rrset.from_text("a.b.stale.", 2, IN, NS, "ns.a.b.stale.") + ) + r.additional.append( + dns.rrset.from_text("ns.a.b.stale.", 2, IN, A, "10.53.0.3") + ) elif endswith(lqname, "b.stale."): # Delegate to ns.b.stale. - r.authority.append(dns.rrset.from_text("b.stale.", 2, IN, NS, "ns.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.4")) + r.authority.append( + dns.rrset.from_text("b.stale.", 2, IN, NS, "ns.b.stale.") + ) + r.additional.append( + dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.4") + ) elif lqname == "stale." and rrtype == NS: # NS query at the apex. r.answer.append(dns.rrset.from_text("stale.", 2, IN, NS, "ns2.stale.")) r.flags |= dns.flags.AA elif lqname == "stale." and rrtype == SOA: # SOA query at the apex. - r.answer.append(dns.rrset.from_text("stale.", 2, IN, SOA, "ns2.stale. hostmaster.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + "stale.", 2, IN, SOA, "ns2.stale. hostmaster.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA elif lqname == "stale.": # NODATA answer - r.authority.append(dns.rrset.from_text("stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + "stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5" + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + "stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5" + ) + ) r.set_rcode(NXDOMAIN) return r elif endswith(lqname, "bad."): @@ -168,43 +245,72 @@ def create_response(msg): # Good/bad/ugly differs only in how we treat non-empty terminals if endswith(lqname, "zoop.boing."): - r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix)) - elif lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z." and rrtype == A: + r.authority.append( + dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix) + ) + elif ( + lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z." + and rrtype == A + ): r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2")) r.flags |= dns.flags.AA elif lqname == "" and rrtype == NS: r.answer.append(dns.rrset.from_text(suffix, 30, IN, NS, "ns2." + suffix)) r.flags |= dns.flags.AA elif lqname == "ns2." and rrtype == A: - r.answer.append(dns.rrset.from_text("ns2."+suffix, 30, IN, A, "10.53.0.2")) + r.answer.append(dns.rrset.from_text("ns2." + suffix, 30, IN, A, "10.53.0.2")) r.flags |= dns.flags.AA elif lqname == "ns2." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("ns2."+suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::2")) + r.answer.append( + dns.rrset.from_text("ns2." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::2") + ) r.flags |= dns.flags.AA elif lqname == "ns3." and rrtype == A: - r.answer.append(dns.rrset.from_text("ns3."+suffix, 30, IN, A, "10.53.0.3")) + r.answer.append(dns.rrset.from_text("ns3." + suffix, 30, IN, A, "10.53.0.3")) r.flags |= dns.flags.AA elif lqname == "ns3." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("ns3."+suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::3")) + r.answer.append( + dns.rrset.from_text("ns3." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::3") + ) r.flags |= dns.flags.AA elif lqname == "ns4." and rrtype == A: - r.answer.append(dns.rrset.from_text("ns4."+suffix, 30, IN, A, "10.53.0.4")) + r.answer.append(dns.rrset.from_text("ns4." + suffix, 30, IN, A, "10.53.0.4")) r.flags |= dns.flags.AA elif lqname == "ns4." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("ns4."+suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::4")) + r.answer.append( + dns.rrset.from_text("ns4." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::4") + ) r.flags |= dns.flags.AA elif lqname == "a.bit.longer.ns.name." and rrtype == A: - r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, A, "10.53.0.4")) + r.answer.append( + dns.rrset.from_text("a.bit.longer.ns.name." + suffix, 1, IN, A, "10.53.0.4") + ) r.flags |= dns.flags.AA elif lqname == "a.bit.longer.ns.name." and rrtype == AAAA: - r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4")) + r.answer.append( + dns.rrset.from_text( + "a.bit.longer.ns.name." + suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4" + ) + ) r.flags |= dns.flags.AA else: - r.authority.append(dns.rrset.from_text(suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) - if bad or not \ - (endswith("icky.icky.icky.ptang.zoop.boing.", lqname) or \ - endswith("many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.", lqname) or \ - endswith("a.bit.longer.ns.name.", lqname)): + r.authority.append( + dns.rrset.from_text( + suffix, + 1, + IN, + SOA, + "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) + if bad or not ( + endswith("icky.icky.icky.ptang.zoop.boing.", lqname) + or endswith( + "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.", + lqname, + ) + or endswith("a.bit.longer.ns.name.", lqname) + ): r.set_rcode(NXDOMAIN) if ugly: r.set_rcode(FORMERR) @@ -214,11 +320,12 @@ def create_response(msg): def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -229,8 +336,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.2" ip6 = "fd92:7065:b8e:ffff::2" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -248,17 +357,17 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -277,8 +386,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/qmin/ans3/ans.py b/bin/tests/system/qmin/ans3/ans.py index 7416e6f18f..b2883a1b7d 100755 --- a/bin/tests/system/qmin/ans3/ans.py +++ b/bin/tests/system/qmin/ans3/ans.py @@ -31,9 +31,11 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + def endswith(domain, labels): return domain.endswith("." + labels) or domain == labels + ############################################################################ # Respond to a DNS query. # For good. it serves: @@ -54,7 +56,7 @@ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") # get qtype rrtype = m.question[0].rdtype @@ -101,17 +103,31 @@ def create_response(msg): elif rrtype == NS: # NS a.b. r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")) + r.additional.append( + dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3") + ) r.flags |= dns.flags.AA elif rrtype == SOA: # SOA a.b. - r.answer.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA else: # NODATA. - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) else: - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) r.set_rcode(NXDOMAIN) # NXDOMAIN. return r @@ -121,21 +137,51 @@ def create_response(msg): # Good/bad differs only in how we treat non-empty terminals if lqname == "zoop.boing." and rrtype == NS: - r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3."+suffix)) + r.answer.append( + dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3." + suffix) + ) r.flags |= dns.flags.AA elif endswith(lqname, "icky.ptang.zoop.boing."): - r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix)) + r.authority.append( + dns.rrset.from_text( + "icky.ptang.zoop.boing." + suffix, + 1, + IN, + NS, + "a.bit.longer.ns.name." + suffix, + ) + ) elif endswith("icky.ptang.zoop.boing.", lqname): - r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "zoop.boing." + suffix, + 1, + IN, + SOA, + "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) if bad: r.set_rcode(NXDOMAIN) if ugly: r.set_rcode(FORMERR) elif endswith(lqname, "zoop.boing."): - r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "zoop.boing." + suffix, + 1, + IN, + SOA, + "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) r.set_rcode(NXDOMAIN) elif ip6req: - r.authority.append(dns.rrset.from_text("1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns4.good.")) + r.authority.append( + dns.rrset.from_text( + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns4.good." + ) + ) r.additional.append(dns.rrset.from_text("ns4.good.", 60, IN, A, "10.53.0.4")) else: r.set_rcode(REFUSED) @@ -146,11 +192,12 @@ def create_response(msg): def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -161,8 +208,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.3" ip6 = "fd92:7065:b8e:ffff::3" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -180,17 +229,17 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -209,8 +258,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/qmin/ans4/ans.py b/bin/tests/system/qmin/ans4/ans.py index 2c672c8e71..a4cc13c656 100755 --- a/bin/tests/system/qmin/ans4/ans.py +++ b/bin/tests/system/qmin/ans4/ans.py @@ -31,9 +31,11 @@ def logquery(type, qname): with open("qlog", "a") as f: f.write("%s %s\n", type, qname) + def endswith(domain, labels): return domain.endswith("." + labels) or domain == labels + ############################################################################ # Respond to a DNS query. # For good. it serves: @@ -55,7 +57,7 @@ def create_response(msg): m = dns.message.from_wire(msg) qname = m.question[0].name.to_text() lqname = qname.lower() - labels = lqname.split('.') + labels = lqname.split(".") # get qtype rrtype = m.question[0].rdtype @@ -102,30 +104,54 @@ def create_response(msg): elif rrtype == NS: # NS a.b. r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")) + r.additional.append( + dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3") + ) r.flags |= dns.flags.AA elif rrtype == SOA: # SOA a.b. - r.answer.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA else: # NODATA. - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5" + ) + ) elif lqname == "b.stale.": if rrtype == NS: # NS b. r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.b.stale.")) - r.additional.append(dns.rrset.from_text("ns.b.stale.", 1, IN, A, "10.53.0.4")) + r.additional.append( + dns.rrset.from_text("ns.b.stale.", 1, IN, A, "10.53.0.4") + ) r.flags |= dns.flags.AA elif rrtype == SOA: # SOA b. - r.answer.append(dns.rrset.from_text(lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5")) + r.answer.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5" + ) + ) r.flags |= dns.flags.AA else: # NODATA. - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5" + ) + ) else: - r.authority.append(dns.rrset.from_text(lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5")) + r.authority.append( + dns.rrset.from_text( + lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5" + ) + ) r.set_rcode(NXDOMAIN) # NXDOMAIN. return r @@ -141,24 +167,67 @@ def create_response(msg): r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2")) r.flags |= dns.flags.AA elif lqname == "icky.ptang.zoop.boing." and rrtype == NS: - r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name."+suffix)) + r.answer.append( + dns.rrset.from_text( + lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix + ) + ) r.flags |= dns.flags.AA elif endswith(lqname, "icky.ptang.zoop.boing."): - r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1")) + r.authority.append( + dns.rrset.from_text( + "icky.ptang.zoop.boing." + suffix, + 1, + IN, + SOA, + "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1", + ) + ) if bad or not endswith("more.icky.icky.icky.ptang.zoop.boing.", lqname): r.set_rcode(NXDOMAIN) if ugly: r.set_rcode(FORMERR) elif ip6req: r.flags |= dns.flags.AA - if lqname == "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa." and rrtype == TXT: - r.answer.append(dns.rrset.from_text("test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 1, IN, TXT, "long_ip6_name")) - elif endswith("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", lqname): - #NODATA answer - r.authority.append(dns.rrset.from_text("1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, SOA, "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16")) + if ( + lqname + == "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa." + and rrtype == TXT + ): + r.answer.append( + dns.rrset.from_text( + "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + 1, + IN, + TXT, + "long_ip6_name", + ) + ) + elif endswith( + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + lqname, + ): + # NODATA answer + r.authority.append( + dns.rrset.from_text( + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + 60, + IN, + SOA, + "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16", + ) + ) else: # NXDOMAIN - r.authority.append(dns.rrset.from_text("1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, SOA, "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16")) + r.authority.append( + dns.rrset.from_text( + "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", + 60, + IN, + SOA, + "ns4.good. hostmaster.arpa. 2018050100 120 30 320 16", + ) + ) r.set_rcode(NXDOMAIN) else: r.set_rcode(REFUSED) @@ -169,11 +238,12 @@ def create_response(msg): def sigterm(signum, frame): - print ("Shutting down now...") - os.remove('ans.pid') + print("Shutting down now...") + os.remove("ans.pid") running = False sys.exit(0) + ############################################################################ # Main # @@ -184,8 +254,10 @@ def sigterm(signum, frame): ip4 = "10.53.0.4" ip6 = "fd92:7065:b8e:ffff::4" -try: port=int(os.environ['PORT']) -except: port=5300 +try: + port = int(os.environ["PORT"]) +except: + port = 5300 query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) query4_socket.bind((ip4, port)) @@ -203,17 +275,17 @@ except: signal.signal(signal.SIGTERM, sigterm) -f = open('ans.pid', 'w') +f = open("ans.pid", "w") pid = os.getpid() -print (pid, file=f) +print(pid, file=f) f.close() running = True -print ("Listening on %s port %d" % (ip4, port)) +print("Listening on %s port %d" % (ip4, port)) if havev6: - print ("Listening on %s port %d" % (ip6, port)) -print ("Ctrl-c to quit") + print("Listening on %s port %d" % (ip6, port)) +print("Ctrl-c to quit") if havev6: input = [query4_socket, query6_socket] @@ -232,8 +304,9 @@ while running: for s in inputready: if s == query4_socket or s == query6_socket: - print ("Query received on %s" % - (ip4 if s == query4_socket else ip6), end=" ") + print( + "Query received on %s" % (ip4 if s == query4_socket else ip6), end=" " + ) # Handle incoming queries msg = s.recvfrom(65535) rsp = create_response(msg[0]) diff --git a/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py b/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py index 4785babfba..326284739e 100755 --- a/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py +++ b/bin/tests/system/rpzextra/tests-rpz-passthru-logging.py @@ -15,24 +15,24 @@ import os import pytest -pytest.importorskip('dns') +pytest.importorskip("dns") import dns.resolver def test_rpz_passthru_logging(named_port): resolver = dns.resolver.Resolver() - resolver.nameservers = ['10.53.0.1'] + resolver.nameservers = ["10.53.0.1"] resolver.port = named_port # Should generate a log entry into rpz_passthru.txt - ans = resolver.query('allowed.', 'A') + ans = resolver.query("allowed.", "A") for rd in ans: assert rd.address == "10.53.0.2" # baddomain.com isn't allowed (CNAME .), should return NXDOMAIN # Should generate a log entry into rpz.txt with pytest.raises(dns.resolver.NXDOMAIN): - resolver.query('baddomain.', 'A') + resolver.query("baddomain.", "A") rpz_passthru_logfile = os.path.join("ns1", "rpz_passthru.txt") rpz_logfile = os.path.join("ns1", "rpz.txt") @@ -40,11 +40,11 @@ def test_rpz_passthru_logging(named_port): assert os.path.isfile(rpz_passthru_logfile) assert os.path.isfile(rpz_logfile) - with open(rpz_passthru_logfile, encoding='utf-8') as log_file: + with open(rpz_passthru_logfile, encoding="utf-8") as log_file: line = log_file.read() assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" in line - with open(rpz_logfile, encoding='utf-8') as log_file: + with open(rpz_logfile, encoding="utf-8") as log_file: line = log_file.read() assert "rpz QNAME PASSTHRU rewrite allowed/A/IN" not in line assert "rpz QNAME NXDOMAIN rewrite baddomain/A/IN" in line diff --git a/bin/tests/system/shutdown/tests-shutdown.py b/bin/tests/system/shutdown/tests-shutdown.py index b8de379d66..e8fc69e170 100755 --- a/bin/tests/system/shutdown/tests-shutdown.py +++ b/bin/tests/system/shutdown/tests-shutdown.py @@ -21,47 +21,47 @@ import time import pytest -pytest.importorskip('dns') +pytest.importorskip("dns") import dns.exception import dns.resolver def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries): """Creates a number of A queries to run in parallel - in order simulate a slightly more realistic test scenario. + in order simulate a slightly more realistic test scenario. - The main idea of this function is to create and send a bunch - of A queries to a target named instance and during this process - a request for shutting down named will be issued. + The main idea of this function is to create and send a bunch + of A queries to a target named instance and during this process + a request for shutting down named will be issued. - In the process of shutting down named, a couple control connections - are created (by launching rndc) to ensure that the crash was fixed. + In the process of shutting down named, a couple control connections + are created (by launching rndc) to ensure that the crash was fixed. - if kill_method=="rndc" named will be asked to shutdown by - means of rndc stop. - if kill_method=="sigterm" named will be killed by SIGTERM on - POSIX systems or by TerminateProcess() on Windows systems. + if kill_method=="rndc" named will be asked to shutdown by + means of rndc stop. + if kill_method=="sigterm" named will be killed by SIGTERM on + POSIX systems or by TerminateProcess() on Windows systems. - :param named_proc: named process instance - :type named_proc: subprocess.Popen + :param named_proc: named process instance + :type named_proc: subprocess.Popen - :param resolver: target resolver - :type resolver: dns.resolver.Resolver + :param resolver: target resolver + :type resolver: dns.resolver.Resolver - :param rndc_cmd: rndc command with default arguments - :type rndc_cmd: list of strings, e.g. ["rndc", "-p", "23750"] + :param rndc_cmd: rndc command with default arguments + :type rndc_cmd: list of strings, e.g. ["rndc", "-p", "23750"] - :kill_method: "rndc" or "sigterm" - :type kill_method: str + :kill_method: "rndc" or "sigterm" + :type kill_method: str - :param n_workers: Number of worker threads to create - :type n_workers: int + :param n_workers: Number of worker threads to create + :type n_workers: int - :param n_queries: Total number of queries to send - :type n_queries: int + :param n_queries: Total number of queries to send + :type n_queries: int """ -# pylint: disable-msg=too-many-arguments -# pylint: disable-msg=too-many-locals + # pylint: disable-msg=too-many-arguments + # pylint: disable-msg=too-many-locals # helper function, args must be a list or tuple with arguments to rndc. def launch_rndc(args): @@ -91,21 +91,22 @@ def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries): else: tag = "bad" length = random.randint(4, 10) - relname = "".join(letters[ - random.randrange(len(letters))] for i in range(length)) + relname = "".join( + letters[random.randrange(len(letters))] for i in range(length) + ) qname = relname + ".test" - futures[executor.submit(resolver.query, qname, 'A')] = tag + futures[executor.submit(resolver.query, qname, "A")] = tag elif shutdown: # We attempt to stop named in the middle shutdown = False if kill_method == "rndc": - futures[executor.submit(launch_rndc, ['stop'])] = 'stop' + futures[executor.submit(launch_rndc, ["stop"])] = "stop" else: - futures[executor.submit(named_proc.terminate)] = 'kill' + futures[executor.submit(named_proc.terminate)] = "kill" else: # We attempt to send couple rndc commands while named is # being shutdown - futures[executor.submit(launch_rndc, ['status'])] = 'status' + futures[executor.submit(launch_rndc, ["status"])] = "status" ret_code = -1 for future in as_completed(futures): @@ -120,9 +121,11 @@ def do_work(named_proc, resolver, rndc_cmd, kill_method, n_workers, n_queries): if futures[future] == "stop": ret_code = result - except (dns.resolver.NXDOMAIN, - dns.resolver.NoNameservers, - dns.exception.Timeout): + except ( + dns.resolver.NXDOMAIN, + dns.resolver.NoNameservers, + dns.exception.Timeout, + ): pass if kill_method == "rndc": @@ -148,12 +151,11 @@ def test_named_shutdown(named_port, control_port): assert os.path.isfile(rndc_cfg) # rndc command with default arguments. - rndc_cmd = [rndc, "-c", rndc_cfg, "-p", str(control_port), - "-s", "10.53.0.3"] + rndc_cmd = [rndc, "-c", rndc_cfg, "-p", str(control_port), "-s", "10.53.0.3"] # We create a resolver instance that will be used to send queries. resolver = dns.resolver.Resolver() - resolver.nameservers = ['10.53.0.3'] + resolver.nameservers = ["10.53.0.3"] resolver.port = named_port # We test named shutting down using two methods: @@ -168,13 +170,14 @@ def test_named_shutdown(named_port, control_port): # wait for named to finish loading for _ in range(10): try: - resolver.query('version.bind', 'TXT', 'CH') + resolver.query("version.bind", "TXT", "CH") break except (dns.resolver.NoNameservers, dns.exception.Timeout): time.sleep(1) - do_work(named_proc, resolver, rndc_cmd, - kill_method, n_workers=12, n_queries=16) + do_work( + named_proc, resolver, rndc_cmd, kill_method, n_workers=12, n_queries=16 + ) # Wait named to exit for a maximum of MAX_TIMEOUT seconds. MAX_TIMEOUT = 10 diff --git a/bin/tests/system/statschannel/generic.py b/bin/tests/system/statschannel/generic.py index e4cf82cec5..6688ff6db0 100644 --- a/bin/tests/system/statschannel/generic.py +++ b/bin/tests/system/statschannel/generic.py @@ -14,7 +14,7 @@ import os # ISO datetime format without msec -fmt = '%Y-%m-%dT%H:%M:%SZ' +fmt = "%Y-%m-%dT%H:%M:%SZ" # The constants were taken from BIND 9 source code (lib/dns/zone.c) max_refresh = timedelta(seconds=2419200) # 4 weeks @@ -71,9 +71,9 @@ def zone_mtime(zonedir, name): def test_zone_timers_primary(fetch_zones, load_timers, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] - zonedir = kwargs['zonedir'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] + zonedir = kwargs["zonedir"] zones = fetch_zones(statsip, statsport) @@ -85,9 +85,9 @@ def test_zone_timers_primary(fetch_zones, load_timers, **kwargs): def test_zone_timers_secondary(fetch_zones, load_timers, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] - zonedir = kwargs['zonedir'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] + zonedir = kwargs["zonedir"] zones = fetch_zones(statsip, statsport) @@ -99,12 +99,12 @@ def test_zone_timers_secondary(fetch_zones, load_timers, **kwargs): def test_zone_with_many_keys(fetch_zones, load_zone, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] zones = fetch_zones(statsip, statsport) for zone in zones: name = load_zone(zone) - if name == 'manykeys': + if name == "manykeys": check_manykeys(name) diff --git a/bin/tests/system/statschannel/generic_dnspython.py b/bin/tests/system/statschannel/generic_dnspython.py index 88dabbca08..37e6e89f14 100644 --- a/bin/tests/system/statschannel/generic_dnspython.py +++ b/bin/tests/system/statschannel/generic_dnspython.py @@ -20,8 +20,9 @@ TIMEOUT = 10 def create_msg(qname, qtype): - msg = dns.message.make_query(qname, qtype, want_dnssec=True, - use_edns=0, payload=4096) + msg = dns.message.make_query( + qname, qtype, want_dnssec=True, use_edns=0, payload=4096 + ) return msg @@ -43,15 +44,16 @@ def tcp_query(ip, port, msg): def create_expected(data): - expected = {"dns-tcp-requests-sizes-received-ipv4": defaultdict(int), - "dns-tcp-responses-sizes-sent-ipv4": defaultdict(int), - "dns-tcp-requests-sizes-received-ipv6": defaultdict(int), - "dns-tcp-responses-sizes-sent-ipv6": defaultdict(int), - "dns-udp-requests-sizes-received-ipv4": defaultdict(int), - "dns-udp-requests-sizes-received-ipv6": defaultdict(int), - "dns-udp-responses-sizes-sent-ipv4": defaultdict(int), - "dns-udp-responses-sizes-sent-ipv6": defaultdict(int), - } + expected = { + "dns-tcp-requests-sizes-received-ipv4": defaultdict(int), + "dns-tcp-responses-sizes-sent-ipv4": defaultdict(int), + "dns-tcp-requests-sizes-received-ipv6": defaultdict(int), + "dns-tcp-responses-sizes-sent-ipv6": defaultdict(int), + "dns-udp-requests-sizes-received-ipv4": defaultdict(int), + "dns-udp-requests-sizes-received-ipv6": defaultdict(int), + "dns-udp-responses-sizes-sent-ipv4": defaultdict(int), + "dns-udp-responses-sizes-sent-ipv6": defaultdict(int), + } for k, v in data.items(): for kk, vv in v.items(): @@ -89,9 +91,9 @@ def check_traffic(data, expected): def test_traffic(fetch_traffic, **kwargs): - statsip = kwargs['statsip'] - statsport = kwargs['statsport'] - port = kwargs['port'] + statsip = kwargs["statsip"] + statsport = kwargs["statsport"] + port = kwargs["port"] data = fetch_traffic(statsip, statsport) exp = create_expected(data) diff --git a/bin/tests/system/statschannel/tests-json.py b/bin/tests/system/statschannel/tests-json.py index 373f98d30b..d94a32f7da 100755 --- a/bin/tests/system/statschannel/tests-json.py +++ b/bin/tests/system/statschannel/tests-json.py @@ -19,16 +19,18 @@ import pytest import generic -pytestmark = pytest.mark.skipif(not os.environ.get('HAVEJSONSTATS'), - reason='json-c support disabled in the build') -requests = pytest.importorskip('requests') +pytestmark = pytest.mark.skipif( + not os.environ.get("HAVEJSONSTATS"), reason="json-c support disabled in the build" +) +requests = pytest.importorskip("requests") # JSON helper functions def fetch_zones_json(statsip, statsport): - r = requests.get("http://{}:{}/json/v1/zones".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/json/v1/zones".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 data = r.json() @@ -37,8 +39,9 @@ def fetch_zones_json(statsip, statsport): def fetch_traffic_json(statsip, statsport): - r = requests.get("http://{}:{}/json/v1/traffic".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/json/v1/traffic".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 data = r.json() @@ -48,52 +51,61 @@ def fetch_traffic_json(statsip, statsport): def load_timers_json(zone, primary=True): - name = zone['name'] + name = zone["name"] # Check if the primary zone timer exists - assert 'loaded' in zone - loaded = datetime.strptime(zone['loaded'], generic.fmt) + assert "loaded" in zone + loaded = datetime.strptime(zone["loaded"], generic.fmt) if primary: # Check if the secondary zone timers does not exist - assert 'expires' not in zone - assert 'refresh' not in zone + assert "expires" not in zone + assert "refresh" not in zone expires = None refresh = None else: - assert 'expires' in zone - assert 'refresh' in zone - expires = datetime.strptime(zone['expires'], generic.fmt) - refresh = datetime.strptime(zone['refresh'], generic.fmt) + assert "expires" in zone + assert "refresh" in zone + expires = datetime.strptime(zone["expires"], generic.fmt) + refresh = datetime.strptime(zone["refresh"], generic.fmt) return (name, loaded, expires, refresh) def load_zone_json(zone): - name = zone['name'] + name = zone["name"] return name def test_zone_timers_primary_json(statsport): - generic.test_zone_timers_primary(fetch_zones_json, load_timers_json, - statsip="10.53.0.1", statsport=statsport, - zonedir="ns1") + generic.test_zone_timers_primary( + fetch_zones_json, + load_timers_json, + statsip="10.53.0.1", + statsport=statsport, + zonedir="ns1", + ) def test_zone_timers_secondary_json(statsport): - generic.test_zone_timers_secondary(fetch_zones_json, load_timers_json, - statsip="10.53.0.3", statsport=statsport, - zonedir="ns3") + generic.test_zone_timers_secondary( + fetch_zones_json, + load_timers_json, + statsip="10.53.0.3", + statsport=statsport, + zonedir="ns3", + ) def test_zone_with_many_keys_json(statsport): - generic.test_zone_with_many_keys(fetch_zones_json, load_zone_json, - statsip="10.53.0.2", statsport=statsport) + generic.test_zone_with_many_keys( + fetch_zones_json, load_zone_json, statsip="10.53.0.2", statsport=statsport + ) def test_traffic_json(named_port, statsport): - generic_dnspython = pytest.importorskip('generic_dnspython') - generic_dnspython.test_traffic(fetch_traffic_json, - statsip="10.53.0.2", statsport=statsport, - port=named_port) + generic_dnspython = pytest.importorskip("generic_dnspython") + generic_dnspython.test_traffic( + fetch_traffic_json, statsip="10.53.0.2", statsport=statsport, port=named_port + ) diff --git a/bin/tests/system/statschannel/tests-xml.py b/bin/tests/system/statschannel/tests-xml.py index 73b6e909f3..423754916a 100755 --- a/bin/tests/system/statschannel/tests-xml.py +++ b/bin/tests/system/statschannel/tests-xml.py @@ -20,41 +20,43 @@ import pytest import generic -pytestmark = pytest.mark.skipif(not os.environ.get('HAVEXMLSTATS'), - reason='libxml2 support disabled in the build') -requests = pytest.importorskip('requests') +pytestmark = pytest.mark.skipif( + not os.environ.get("HAVEXMLSTATS"), reason="libxml2 support disabled in the build" +) +requests = pytest.importorskip("requests") # XML helper functions def fetch_zones_xml(statsip, statsport): - r = requests.get("http://{}:{}/xml/v3/zones".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/xml/v3/zones".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 root = ET.fromstring(r.text) default_view = None - for view in root.find('views').iter('view'): - if view.attrib['name'] == "_default": + for view in root.find("views").iter("view"): + if view.attrib["name"] == "_default": default_view = view break assert default_view is not None - return default_view.find('zones').findall('zone') + return default_view.find("zones").findall("zone") def fetch_traffic_xml(statsip, statsport): - def load_counters(data): out = {} for counter in data.findall("counter"): - out[counter.attrib['name']] = int(counter.text) + out[counter.attrib["name"]] = int(counter.text) return out - r = requests.get("http://{}:{}/xml/v3/traffic".format(statsip, statsport), - timeout=600) + r = requests.get( + "http://{}:{}/xml/v3/traffic".format(statsip, statsport), timeout=600 + ) assert r.status_code == 200 root = ET.fromstring(r.text) @@ -64,7 +66,7 @@ def fetch_traffic_xml(statsip, statsport): for proto in ["udp", "tcp"]: proto_root = root.find("traffic").find(ip).find(proto) for counters in proto_root.findall("counters"): - if counters.attrib['type'] == "request-size": + if counters.attrib["type"] == "request-size": key = "dns-{}-requests-sizes-received-{}".format(proto, ip) else: key = "dns-{}-responses-sizes-sent-{}".format(proto, ip) @@ -77,14 +79,14 @@ def fetch_traffic_xml(statsip, statsport): def load_timers_xml(zone, primary=True): - name = zone.attrib['name'] + name = zone.attrib["name"] - loaded_el = zone.find('loaded') + loaded_el = zone.find("loaded") assert loaded_el is not None loaded = datetime.strptime(loaded_el.text, generic.fmt) - expires_el = zone.find('expires') - refresh_el = zone.find('refresh') + expires_el = zone.find("expires") + refresh_el = zone.find("refresh") if primary: assert expires_el is None assert refresh_el is None @@ -100,30 +102,39 @@ def load_timers_xml(zone, primary=True): def load_zone_xml(zone): - name = zone.attrib['name'] + name = zone.attrib["name"] return name def test_zone_timers_primary_xml(statsport): - generic.test_zone_timers_primary(fetch_zones_xml, load_timers_xml, - statsip="10.53.0.1", statsport=statsport, - zonedir="ns1") + generic.test_zone_timers_primary( + fetch_zones_xml, + load_timers_xml, + statsip="10.53.0.1", + statsport=statsport, + zonedir="ns1", + ) def test_zone_timers_secondary_xml(statsport): - generic.test_zone_timers_secondary(fetch_zones_xml, load_timers_xml, - statsip="10.53.0.3", statsport=statsport, - zonedir="ns3") + generic.test_zone_timers_secondary( + fetch_zones_xml, + load_timers_xml, + statsip="10.53.0.3", + statsport=statsport, + zonedir="ns3", + ) def test_zone_with_many_keys_xml(statsport): - generic.test_zone_with_many_keys(fetch_zones_xml, load_zone_xml, - statsip="10.53.0.2", statsport=statsport) + generic.test_zone_with_many_keys( + fetch_zones_xml, load_zone_xml, statsip="10.53.0.2", statsport=statsport + ) def test_traffic_xml(named_port, statsport): - generic_dnspython = pytest.importorskip('generic_dnspython') - generic_dnspython.test_traffic(fetch_traffic_xml, - statsip="10.53.0.2", statsport=statsport, - port=named_port) + generic_dnspython = pytest.importorskip("generic_dnspython") + generic_dnspython.test_traffic( + fetch_traffic_xml, statsip="10.53.0.2", statsport=statsport, port=named_port + ) diff --git a/bin/tests/system/tcp/ans6/ans.py b/bin/tests/system/tcp/ans6/ans.py index 5cc98538fb..4595ddcd07 100644 --- a/bin/tests/system/tcp/ans6/ans.py +++ b/bin/tests/system/tcp/ans6/ans.py @@ -42,10 +42,11 @@ import time # Timeout for establishing all connections requested by a single 'open' command. OPEN_TIMEOUT = 2 -VERSION_QUERY = b'\x00\x1e\xaf\xb8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03' +VERSION_QUERY = b"\x00\x1e\xaf\xb8\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03" + def log(msg): - print(datetime.datetime.now().strftime('%d-%b-%Y %H:%M:%S.%f ') + msg) + print(datetime.datetime.now().strftime("%d-%b-%Y %H:%M:%S.%f ") + msg) def open_connections(active_conns, count, host, port): @@ -58,14 +59,14 @@ def open_connections(active_conns, count, host, port): except socket.error: family = socket.AF_INET6 - log('Opening %d connections...' % count) + log("Opening %d connections..." % count) for _ in range(count): sock = socket.socket(family, socket.SOCK_STREAM) sock.setblocking(0) err = sock.connect_ex((host, port)) if err not in (0, errno.EINPROGRESS): - log('%s on connect for socket %s' % (errno.errorcode[err], sock)) + log("%s on connect for socket %s" % (errno.errorcode[err], sock)) errors.append(sock) else: queued.append(sock) @@ -81,35 +82,35 @@ def open_connections(active_conns, count, host, port): queued.remove(sock) err = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) if err: - log('%s for socket %s' % (errno.errorcode[err], sock)) + log("%s for socket %s" % (errno.errorcode[err], sock)) errors.append(sock) else: sock.send(VERSION_QUERY) active_conns.append(sock) if errors: - log('result=FAIL: %d connection(s) failed' % len(errors)) + log("result=FAIL: %d connection(s) failed" % len(errors)) elif queued: - log('result=FAIL: Timed out, aborting %d pending connections' % len(queued)) + log("result=FAIL: Timed out, aborting %d pending connections" % len(queued)) for sock in queued: sock.close() else: - log('result=OK: Successfully opened %d connections' % count) + log("result=OK: Successfully opened %d connections" % count) def close_connections(active_conns, count): - log('Closing %s connections...' % "all" if count == 0 else str(count)) + log("Closing %s connections..." % "all" if count == 0 else str(count)) if count == 0: count = len(active_conns) for _ in range(count): sock = active_conns.pop(0) sock.close() - log('result=OK: Successfully closed %d connections' % count) + log("result=OK: Successfully closed %d connections" % count) def sigterm(*_): - log('SIGTERM received, shutting down') - os.remove('ans.pid') + log("SIGTERM received, shutting down") + os.remove("ans.pid") sys.exit(0) @@ -118,16 +119,16 @@ def main(): signal.signal(signal.SIGTERM, sigterm) - with open('ans.pid', 'w') as pidfile: + with open("ans.pid", "w") as pidfile: print(os.getpid(), file=pidfile) - listenip = '10.53.0.6' + listenip = "10.53.0.6" try: - port = int(os.environ['CONTROLPORT']) + port = int(os.environ["CONTROLPORT"]) except KeyError: port = 5309 - log('Listening on %s:%d' % (listenip, port)) + log("Listening on %s:%d" % (listenip, port)) ctlsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ctlsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -136,21 +137,21 @@ def main(): while True: (clientsock, _) = ctlsock.accept() - log('Accepted control connection from %s' % clientsock) - cmdline = clientsock.recv(512).decode('ascii').strip() + log("Accepted control connection from %s" % clientsock) + cmdline = clientsock.recv(512).decode("ascii").strip() if cmdline: - log('Received command: %s' % cmdline) + log("Received command: %s" % cmdline) cmd = cmdline.split() - if cmd[0] == 'open': + if cmd[0] == "open": count, host, port = cmd[1:] open_connections(active_conns, int(count), host, int(port)) - elif cmd[0] == 'close': - (count, ) = cmd[1:] + elif cmd[0] == "close": + (count,) = cmd[1:] close_connections(active_conns, int(count)) else: - log('result=FAIL: Unknown command') + log("result=FAIL: Unknown command") clientsock.close() -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/bin/tests/system/tcp/tests-tcp.py b/bin/tests/system/tcp/tests-tcp.py index e641ad9103..b38e1de688 100644 --- a/bin/tests/system/tcp/tests-tcp.py +++ b/bin/tests/system/tcp/tests-tcp.py @@ -19,7 +19,7 @@ import time import pytest -pytest.importorskip('dns', minversion='2.0.0') +pytest.importorskip("dns", minversion="2.0.0") import dns.message import dns.query @@ -54,8 +54,8 @@ def test_tcp_garbage(named_port): # Send DNS message shorter than DNS message header (12), # this should cause the connection to be terminated - sock.send(struct.pack('!H', 11)) - sock.send(struct.pack('!s', b'0123456789a')) + sock.send(struct.pack("!H", 11)) + sock.send(struct.pack("!s", b"0123456789a")) with pytest.raises(EOFError): try: @@ -96,8 +96,7 @@ def test_close_wait(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) (response, rtime) = dns.query.receive_tcp(sock, timeout()) - msg = dns.message.make_query("a.example.", "A", use_edns=0, - payload=1232) + msg = dns.message.make_query("a.example.", "A", use_edns=0, payload=1232) (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Shutdown the socket, but ignore the other side closing the socket diff --git a/bin/tests/system/timeouts/tests-tcp.py b/bin/tests/system/timeouts/tests-tcp.py index 74d7cb695f..994a9d746c 100644 --- a/bin/tests/system/timeouts/tests-tcp.py +++ b/bin/tests/system/timeouts/tests-tcp.py @@ -18,7 +18,7 @@ import time import pytest -pytest.importorskip('dns', minversion='2.0.0') +pytest.importorskip("dns", minversion="2.0.0") import dns.edns import dns.message import dns.name @@ -33,8 +33,9 @@ TIMEOUT = 10 def create_msg(qname, qtype): - msg = dns.message.make_query(qname, qtype, want_dnssec=True, - use_edns=0, payload=4096) + msg = dns.message.make_query( + qname, qtype, want_dnssec=True, use_edns=0, payload=4096 + ) return msg @@ -94,7 +95,7 @@ def test_keepalive_timeout(named_port): # Keepalive is 7 seconds, so the third message should succeed. # msg = create_msg("example.", "A") - kopt = dns.edns.GenericOption(11, b'\x00') + kopt = dns.edns.GenericOption(11, b"\x00") msg.use_edns(edns=True, payload=4096, options=[kopt]) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: @@ -163,18 +164,22 @@ def test_long_axfr(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Receive the initial DNS message with SOA - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) assert soa is not None # Pull DNS message from wire until the second SOA is received while True: - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) if soa is not None: break assert soa is not None @@ -216,10 +221,12 @@ def test_max_transfer_idle_out(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Receive the initial DNS message with SOA - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) assert soa is not None time.sleep(61) # max-transfer-idle-out is 1 minute @@ -227,11 +234,12 @@ def test_max_transfer_idle_out(named_port): with pytest.raises(ConnectionResetError): # Process queued TCP messages while True: - (response, rtime) = \ - dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) if soa is not None: break assert soa is None @@ -247,21 +255,24 @@ def test_max_transfer_time_out(named_port): (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) # Receive the initial DNS message with SOA - (response, rtime) = dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) assert soa is not None # The loop should timeout at the 5 minutes (max-transfer-time-out) with pytest.raises(EOFError): while True: time.sleep(1) - (response, rtime) = \ - dns.query.receive_tcp(sock, timeout(), - one_rr_per_rrset=True) - soa = response.get_rrset(dns.message.ANSWER, name, - dns.rdataclass.IN, dns.rdatatype.SOA) + (response, rtime) = dns.query.receive_tcp( + sock, timeout(), one_rr_per_rrset=True + ) + soa = response.get_rrset( + dns.message.ANSWER, name, dns.rdataclass.IN, dns.rdatatype.SOA + ) if soa is not None: break assert soa is None diff --git a/bin/tests/system/wildcard/tests-wildcard.py b/bin/tests/system/wildcard/tests-wildcard.py index f4134225e1..66166f2a9e 100755 --- a/bin/tests/system/wildcard/tests-wildcard.py +++ b/bin/tests/system/wildcard/tests-wildcard.py @@ -45,19 +45,21 @@ from hypothesis.strategies import binary, integers # labels of a zone with * A 192.0.2.1 wildcard -WILDCARD_ZONE = ('allwild', 'test', '') +WILDCARD_ZONE = ("allwild", "test", "") WILDCARD_RDTYPE = dns.rdatatype.A -WILDCARD_RDATA = '192.0.2.1' -IPADDR = '10.53.0.1' +WILDCARD_RDATA = "192.0.2.1" +IPADDR = "10.53.0.1" TIMEOUT = 5 # seconds, just a sanity check # Helpers def is_nonexpanding_rdtype(rdtype): """skip meta types to avoid weird rcodes caused by AXFR etc.; RFC 6895""" - return not(rdtype == WILDCARD_RDTYPE - or dns.rdatatype.is_metatype(rdtype) # known metatypes: OPT ... - or 128 <= rdtype <= 255) # unknown meta types + return not ( + rdtype == WILDCARD_RDTYPE + or dns.rdatatype.is_metatype(rdtype) # known metatypes: OPT ... + or 128 <= rdtype <= 255 + ) # unknown meta types def tcp_query(where, port, qname, qtype): @@ -67,15 +69,16 @@ def tcp_query(where, port, qname, qtype): def query(where, port, label, rdtype): - labels = (label, ) + WILDCARD_ZONE + labels = (label,) + WILDCARD_ZONE qname = dns.name.Name(labels) return tcp_query(where, port, qname, rdtype) # Tests -@given(label=binary(min_size=1, max_size=63), - rdtype=integers(min_value=0, max_value=65535).filter( - is_nonexpanding_rdtype)) +@given( + label=binary(min_size=1, max_size=63), + rdtype=integers(min_value=0, max_value=65535).filter(is_nonexpanding_rdtype), +) def test_wildcard_rdtype_mismatch(label, rdtype, named_port): """any label non-matching rdtype must result in to NODATA""" check_answer_nodata(*query(IPADDR, named_port, label, rdtype)) @@ -97,10 +100,13 @@ def check_answer_noerror(querymsg, answer): assert querymsg.is_response(answer), str(answer) assert answer.rcode() == dns.rcode.NOERROR, str(answer) assert len(querymsg.question) == 1, str(answer) - expected_answer = [dns.rrset.from_text( - querymsg.question[0].name, - 300, # TTL, ignored by dnspython comparison - dns.rdataclass.IN, - WILDCARD_RDTYPE, - WILDCARD_RDATA)] + expected_answer = [ + dns.rrset.from_text( + querymsg.question[0].name, + 300, # TTL, ignored by dnspython comparison + dns.rdataclass.IN, + WILDCARD_RDTYPE, + WILDCARD_RDATA, + ) + ] assert answer.answer == expected_answer, str(answer) diff --git a/dangerfile.py b/dangerfile.py index 5a7b564758..2f139f79aa 100644 --- a/dangerfile.py +++ b/dangerfile.py @@ -15,24 +15,30 @@ import re # Helper functions and variables + def added_lines(target_branch, paths): import subprocess - subprocess.check_output(['/usr/bin/git', 'fetch', '--depth', '1', 'origin', - target_branch]) - diff = subprocess.check_output(['/usr/bin/git', 'diff', 'FETCH_HEAD..', - '--'] + paths) + + subprocess.check_output( + ["/usr/bin/git", "fetch", "--depth", "1", "origin", target_branch] + ) + diff = subprocess.check_output( + ["/usr/bin/git", "diff", "FETCH_HEAD..", "--"] + paths + ) added_lines = [] for line in diff.splitlines(): - if line.startswith(b'+') and not line.startswith(b'+++'): + if line.startswith(b"+") and not line.startswith(b"+++"): added_lines.append(line) return added_lines -def lines_containing(lines, string): - return [l for l in lines if bytes(string, 'utf-8') in l] -changes_issue_or_mr_id_regex = re.compile(br'\[(GL [#!]|RT #)[0-9]+\]') -relnotes_issue_or_mr_id_regex = re.compile(br':gl:`[#!][0-9]+`') -release_notes_regex = re.compile(r'doc/(arm|notes)/notes-.*\.(rst|xml)') +def lines_containing(lines, string): + return [l for l in lines if bytes(string, "utf-8") in l] + + +changes_issue_or_mr_id_regex = re.compile(rb"\[(GL [#!]|RT #)[0-9]+\]") +relnotes_issue_or_mr_id_regex = re.compile(rb":gl:`[#!][0-9]+`") +release_notes_regex = re.compile(r"doc/(arm|notes)/notes-.*\.(rst|xml)") modified_files = danger.git.modified_files mr_labels = danger.gitlab.mr.labels @@ -75,33 +81,39 @@ fixup_error_logged = False for commit in danger.git.commits: message_lines = commit.message.splitlines() subject = message_lines[0] - if (not fixup_error_logged and - (subject.startswith('fixup!') or - subject.startswith('Apply suggestion'))): - fail('Fixup commits are still present in this merge request. ' - 'Please squash them before merging.') - fixup_error_logged = True - if len(subject) > 72 and not subject.startswith('Merge branch '): - warn( - f'Subject line for commit {commit.sha} is too long: ' - f'```{subject}``` ({len(subject)} > 72 characters).' + if not fixup_error_logged and ( + subject.startswith("fixup!") or subject.startswith("Apply suggestion") + ): + fail( + "Fixup commits are still present in this merge request. " + "Please squash them before merging." ) - if subject[-1] == '.': - fail(f'Trailing dot found in the subject of commit {commit.sha}.') + fixup_error_logged = True + if len(subject) > 72 and not subject.startswith("Merge branch "): + warn( + f"Subject line for commit {commit.sha} is too long: " + f"```{subject}``` ({len(subject)} > 72 characters)." + ) + if subject[-1] == ".": + fail(f"Trailing dot found in the subject of commit {commit.sha}.") if len(message_lines) > 1 and message_lines[1]: - fail(f'No empty line after subject for commit {commit.sha}.') - if (len(message_lines) < 3 and - 'fixup! ' not in subject and - ' CHANGES ' not in subject and - ' release note' not in subject): - warn(f'Please write a log message for commit {commit.sha}.') + fail(f"No empty line after subject for commit {commit.sha}.") + if ( + len(message_lines) < 3 + and "fixup! " not in subject + and " CHANGES " not in subject + and " release note" not in subject + ): + warn(f"Please write a log message for commit {commit.sha}.") for line in message_lines[2:]: - if (len(line) > 72 and - not line.startswith(' ') and - not re.match(r'\[[0-9]+\]', line)): + if ( + len(line) > 72 + and not line.startswith(" ") + and not re.match(r"\[[0-9]+\]", line) + ): warn( - f'Line too long in log message for commit {commit.sha}: ' - f'```{line}``` ({len(line)} > 72 characters).' + f"Line too long in log message for commit {commit.sha}: " + f"```{line}``` ({len(line)} > 72 characters)." ) ############################################################################### @@ -111,7 +123,7 @@ for commit in danger.git.commits: # FAIL if the merge request is not assigned to any milestone. if not danger.gitlab.mr.milestone: - fail('Please assign this merge request to a milestone.') + fail("Please assign this merge request to a milestone.") ############################################################################### # VERSION LABELS @@ -129,15 +141,19 @@ if not danger.gitlab.mr.milestone: # request is not a backport, version labels are used for indicating # backporting preferences.) -backport_label_set = 'Backport' in mr_labels -version_labels = [l for l in mr_labels if l.startswith('v9.')] +backport_label_set = "Backport" in mr_labels +version_labels = [l for l in mr_labels if l.startswith("v9.")] if backport_label_set and len(version_labels) != 1: - fail('The *Backport* label is set for this merge request. ' - 'Please also set exactly one version label (*v9.x*).') + fail( + "The *Backport* label is set for this merge request. " + "Please also set exactly one version label (*v9.x*)." + ) if not backport_label_set and not version_labels: - fail('If this merge request is a backport, set the *Backport* label and ' - 'a single version label (*v9.x*) indicating the target branch. ' - 'If not, set version labels for all targeted backport branches.') + fail( + "If this merge request is a backport, set the *Backport* label and " + "a single version label (*v9.x*) indicating the target branch. " + "If not, set version labels for all targeted backport branches." + ) ############################################################################### # OTHER LABELS @@ -151,12 +167,16 @@ if not backport_label_set and not version_labels: # remind developers about the need to set the latter on merge requests which # passed review.) -if 'Review' not in mr_labels: - warn('This merge request does not have the *Review* label set. ' - 'Please set it if you would like the merge request to be reviewed.') -elif 'LGTM (Merge OK)' not in mr_labels: - warn('This merge request is currently in review. ' - 'It should not be merged until it is marked with the *LGTM* label.') +if "Review" not in mr_labels: + warn( + "This merge request does not have the *Review* label set. " + "Please set it if you would like the merge request to be reviewed." + ) +elif "LGTM (Merge OK)" not in mr_labels: + warn( + "This merge request is currently in review. " + "It should not be merged until it is marked with the *LGTM* label." + ) ############################################################################### # 'CHANGES' FILE @@ -178,25 +198,31 @@ elif 'LGTM (Merge OK)' not in mr_labels: # * The merge request adds a new CHANGES entry that is not a placeholder and # does not contain any GitLab/RT issue/MR identifiers. -changes_modified = 'CHANGES' in modified_files -no_changes_label_set = 'No CHANGES' in mr_labels +changes_modified = "CHANGES" in modified_files +no_changes_label_set = "No CHANGES" in mr_labels if not changes_modified and not no_changes_label_set: - fail('This merge request does not modify `CHANGES`. ' - 'Add a `CHANGES` entry or set the *No CHANGES* label.') + fail( + "This merge request does not modify `CHANGES`. " + "Add a `CHANGES` entry or set the *No CHANGES* label." + ) if changes_modified and no_changes_label_set: - fail('This merge request modifies `CHANGES`. ' - 'Revert `CHANGES` modifications or unset the *No Changes* label.') + fail( + "This merge request modifies `CHANGES`. " + "Revert `CHANGES` modifications or unset the *No Changes* label." + ) -changes_added_lines = added_lines(target_branch, ['CHANGES']) -placeholders_added = lines_containing(changes_added_lines, '[placeholder]') +changes_added_lines = added_lines(target_branch, ["CHANGES"]) +placeholders_added = lines_containing(changes_added_lines, "[placeholder]") identifiers_found = filter(changes_issue_or_mr_id_regex.search, changes_added_lines) if changes_added_lines: if placeholders_added: - if target_branch != 'main': - fail('This MR adds at least one placeholder entry to `CHANGES`. ' - 'It should be targeting the `main` branch.') + if target_branch != "main": + fail( + "This MR adds at least one placeholder entry to `CHANGES`. " + "It should be targeting the `main` branch." + ) elif not any(identifiers_found): - fail('No valid issue/MR identifiers found in added `CHANGES` entries.') + fail("No valid issue/MR identifiers found in added `CHANGES` entries.") ############################################################################### # RELEASE NOTES @@ -221,25 +247,31 @@ if changes_added_lines: # identifiers are found in the lines added to the release notes by this # MR. -release_notes_regex = re.compile(r'doc/(arm|notes)/notes-.*\.(rst|xml)') +release_notes_regex = re.compile(r"doc/(arm|notes)/notes-.*\.(rst|xml)") release_notes_changed = list(filter(release_notes_regex.match, modified_files)) -release_notes_label_set = 'Release Notes' in mr_labels +release_notes_label_set = "Release Notes" in mr_labels if not release_notes_changed: if release_notes_label_set: - fail('This merge request has the *Release Notes* label set. ' - 'Add a release note or unset the *Release Notes* label.') - elif 'Customer' in mr_labels: - warn('This merge request has the *Customer* label set. ' - 'Add a release note unless the changes introduced are trivial.') + fail( + "This merge request has the *Release Notes* label set. " + "Add a release note or unset the *Release Notes* label." + ) + elif "Customer" in mr_labels: + warn( + "This merge request has the *Customer* label set. " + "Add a release note unless the changes introduced are trivial." + ) if release_notes_changed and not release_notes_label_set: - fail('This merge request modifies release notes. ' - 'Revert release note modifications or set the *Release Notes* label.') + fail( + "This merge request modifies release notes. " + "Revert release note modifications or set the *Release Notes* label." + ) if release_notes_changed: notes_added_lines = added_lines(target_branch, release_notes_changed) identifiers_found = filter(relnotes_issue_or_mr_id_regex.search, notes_added_lines) if notes_added_lines and not any(identifiers_found): - warn('No valid issue/MR identifiers found in added release notes.') + warn("No valid issue/MR identifiers found in added release notes.") else: notes_added_lines = [] @@ -251,13 +283,17 @@ else: # identifier is missing from either the added CHANGES entry or the added # release note. -if lines_containing(changes_added_lines, '[security]'): - if not lines_containing(changes_added_lines, '(CVE-20'): - fail('This merge request fixes a security issue. ' - 'Please add a CHANGES entry which includes a CVE identifier.') - if not lines_containing(notes_added_lines, 'CVE-20'): - fail('This merge request fixes a security issue. ' - 'Please add a release note which includes a CVE identifier.') +if lines_containing(changes_added_lines, "[security]"): + if not lines_containing(changes_added_lines, "(CVE-20"): + fail( + "This merge request fixes a security issue. " + "Please add a CHANGES entry which includes a CVE identifier." + ) + if not lines_containing(notes_added_lines, "CVE-20"): + fail( + "This merge request fixes a security issue. " + "Please add a release note which includes a CVE identifier." + ) ############################################################################### # PAIRWISE TESTING @@ -266,13 +302,16 @@ if lines_containing(changes_added_lines, '[security]'): # FAIL if the merge request adds any new ./configure switch without an # associated annotation used for pairwise testing. -configure_added_lines = added_lines(target_branch, ['configure.ac']) -switches_added = (lines_containing(configure_added_lines, 'AC_ARG_ENABLE') + - lines_containing(configure_added_lines, 'AC_ARG_WITH')) -annotations_added = lines_containing(configure_added_lines, '# [pairwise: ') +configure_added_lines = added_lines(target_branch, ["configure.ac"]) +switches_added = lines_containing( + configure_added_lines, "AC_ARG_ENABLE" +) + lines_containing(configure_added_lines, "AC_ARG_WITH") +annotations_added = lines_containing(configure_added_lines, "# [pairwise: ") if len(switches_added) > len(annotations_added): - fail('This merge request adds at least one new `./configure` switch that ' - 'is not annotated for pairwise testing purposes.') + fail( + "This merge request adds at least one new `./configure` switch that " + "is not annotated for pairwise testing purposes." + ) ############################################################################### # USER-VISIBLE LOG LEVELS @@ -281,16 +320,18 @@ if len(switches_added) > len(annotations_added): # WARN if the merge request adds new user-visible log messages (INFO or above) user_visible_log_levels = [ - 'ISC_LOG_INFO', - 'ISC_LOG_NOTICE', - 'ISC_LOG_WARNING', - 'ISC_LOG_ERROR', - 'ISC_LOG_CRITICAL', + "ISC_LOG_INFO", + "ISC_LOG_NOTICE", + "ISC_LOG_WARNING", + "ISC_LOG_ERROR", + "ISC_LOG_CRITICAL", ] -source_added_lines = added_lines(target_branch, ['*.[ch]']) +source_added_lines = added_lines(target_branch, ["*.[ch]"]) for log_level in user_visible_log_levels: - if (lines_containing(source_added_lines, log_level)): - warn('This merge request adds new user-visible log messages with ' - 'level INFO or above. Please double-check log levels and make ' - 'sure none of the messages added is a leftover debug message.') + if lines_containing(source_added_lines, log_level): + warn( + "This merge request adds new user-visible log messages with " + "level INFO or above. Please double-check log levels and make " + "sure none of the messages added is a leftover debug message." + ) break diff --git a/doc/arm/conf.py b/doc/arm/conf.py index 403b6cf529..84061baae2 100644 --- a/doc/arm/conf.py +++ b/doc/arm/conf.py @@ -28,17 +28,18 @@ try: except ImportError: # pylint: disable=too-few-public-methods class ReferenceRole(roles.GenericRole): - ''' + """ The ReferenceRole class (used as a base class by GitLabRefRole below) is only defined in Sphinx >= 2.0.0. For older Sphinx versions, this stub version of the ReferenceRole class is used instead. - ''' + """ + def __init__(self): - super().__init__('', nodes.strong) + super().__init__("", nodes.strong) -GITLAB_BASE_URL = 'https://gitlab.isc.org/isc-projects/bind9/-/' +GITLAB_BASE_URL = "https://gitlab.isc.org/isc-projects/bind9/-/" # Custom Sphinx role enabling automatic hyperlinking to GitLab issues/MRs. @@ -48,25 +49,26 @@ class GitLabRefRole(ReferenceRole): super().__init__() def run(self) -> Tuple[List[Node], List[system_message]]: - gl_identifier = '[GL %s]' % self.target + gl_identifier = "[GL %s]" % self.target - target_id = 'index-%s' % self.env.new_serialno('index') - entries = [('single', 'GitLab; ' + gl_identifier, target_id, '', None)] + target_id = "index-%s" % self.env.new_serialno("index") + entries = [("single", "GitLab; " + gl_identifier, target_id, "", None)] index = addnodes.index(entries=entries) - target = nodes.target('', '', ids=[target_id]) + target = nodes.target("", "", ids=[target_id]) self.inliner.document.note_explicit_target(target) try: refuri = self.build_uri() - reference = nodes.reference('', '', internal=False, refuri=refuri, - classes=['gl']) + reference = nodes.reference( + "", "", internal=False, refuri=refuri, classes=["gl"] + ) if self.has_explicit_title: reference += nodes.strong(self.title, self.title) else: reference += nodes.strong(gl_identifier, gl_identifier) except ValueError: - error_text = 'invalid GitLab identifier %s' % self.target + error_text = "invalid GitLab identifier %s" % self.target msg = self.inliner.reporter.error(error_text, line=self.lineno) prb = self.inliner.problematic(self.rawtext, self.rawtext, msg) return [prb], [msg] @@ -74,16 +76,17 @@ class GitLabRefRole(ReferenceRole): return [index, target, reference], [] def build_uri(self): - if self.target[0] == '#': - return self.base_url + 'issues/%d' % int(self.target[1:]) - if self.target[0] == '!': - return self.base_url + 'merge_requests/%d' % int(self.target[1:]) + if self.target[0] == "#": + return self.base_url + "issues/%d" % int(self.target[1:]) + if self.target[0] == "!": + return self.base_url + "merge_requests/%d" % int(self.target[1:]) raise ValueError def setup(app): - roles.register_local_role('gl', GitLabRefRole(GITLAB_BASE_URL)) - app.add_crossref_type('iscman', 'iscman', 'pair: %s; manual page') + roles.register_local_role("gl", GitLabRefRole(GITLAB_BASE_URL)) + app.add_crossref_type("iscman", "iscman", "pair: %s; manual page") + # # Configuration file for the Sphinx documentation builder. @@ -105,23 +108,25 @@ def setup(app): # -- Project information ----------------------------------------------------- -project = 'BIND 9' +project = "BIND 9" # pylint: disable=redefined-builtin -copyright = '2022, Internet Systems Consortium' -author = 'Internet Systems Consortium' +copyright = "2022, Internet Systems Consortium" +author = "Internet Systems Consortium" m4_vars = {} -with open('../../configure.ac', encoding='utf-8') as configure_ac: +with open("../../configure.ac", encoding="utf-8") as configure_ac: for line in configure_ac: - match = re.match(r'm4_define\(\[(?Pbind_VERSION_[A-Z]+)\], (?P[^)]*)\)dnl', line) + match = re.match( + r"m4_define\(\[(?Pbind_VERSION_[A-Z]+)\], (?P[^)]*)\)dnl", line + ) if match: - m4_vars[match.group('key')] = match.group('val') + m4_vars[match.group("key")] = match.group("val") -version = '%s.%s.%s%s' % ( - m4_vars['bind_VERSION_MAJOR'], - m4_vars['bind_VERSION_MINOR'], - m4_vars['bind_VERSION_PATCH'], - m4_vars['bind_VERSION_EXTRA'], +version = "%s.%s.%s%s" % ( + m4_vars["bind_VERSION_MAJOR"], + m4_vars["bind_VERSION_MINOR"], + m4_vars["bind_VERSION_PATCH"], + m4_vars["bind_VERSION_EXTRA"], ) release = version @@ -133,43 +138,42 @@ release = version extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = [ - '_build', - 'Thumbs.db', - '.DS_Store', - '*.inc.rst' - ] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "*.inc.rst"] # The master toctree document. -master_doc = 'index' +master_doc = "index" # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' -html_static_path = ['_static'] -html_css_files = [ - 'custom.css' -] +html_theme = "sphinx_rtd_theme" +html_static_path = ["_static"] +html_css_files = ["custom.css"] # -- Options for EPUB output ------------------------------------------------- -epub_basename = 'Bv9ARM' +epub_basename = "Bv9ARM" # -- Options for LaTeX output ------------------------------------------------ -latex_engine = 'xelatex' +latex_engine = "xelatex" # pylint disable=line-too-long latex_documents = [ - (master_doc, 'Bv9ARM.tex', 'BIND 9 Administrator Reference Manual', author, 'manual'), - ] + ( + master_doc, + "Bv9ARM.tex", + "BIND 9 Administrator Reference Manual", + author, + "manual", + ), +] latex_logo = "isc-logo.pdf" diff --git a/doc/man/conf.py b/doc/man/conf.py index e4d4cdad63..f805e03bff 100644 --- a/doc/man/conf.py +++ b/doc/man/conf.py @@ -32,13 +32,14 @@ # -- Project information ----------------------------------------------------- -project = 'BIND 9' +project = "BIND 9" # pylint: disable=wrong-import-position import datetime + year = datetime.datetime.now().year # pylint: disable=redefined-builtin copyright = "%d, Internet Systems Consortium" % year -author = 'Internet Systems Consortium' +author = "Internet Systems Consortium" # -- General configuration --------------------------------------------------- @@ -52,56 +53,146 @@ man_make_section_directory = False extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['../arm/_templates'] +templates_path = ["../arm/_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [ - '_build', - 'Thumbs.db', - '.DS_Store', - ] + "_build", + "Thumbs.db", + ".DS_Store", +] # The master toctree document. -master_doc = 'index' +master_doc = "index" # pylint: disable=line-too-long man_pages = [ - ('arpaname', 'arpaname', 'translate IP addresses to the corresponding ARPA names', author, 1), - ('ddns-confgen', 'ddns-confgen', 'ddns key generation tool', author, 8), - ('delv', 'delv', 'DNS lookup and validation utility', author, 1), - ('dig', 'dig', 'DNS lookup utility', author, 1), - ('dnssec-cds', 'dnssec-cds', 'change DS records for a child zone based on CDS/CDNSKEY', author, 1), - ('dnssec-dsfromkey', 'dnssec-dsfromkey', 'DNSSEC DS RR generation tool', author, 1), - ('dnssec-importkey', 'dnssec-importkey', 'import DNSKEY records from external systems so they can be managed', author, 1), - ('dnssec-keyfromlabel', 'dnssec-keyfromlabel', 'DNSSEC key generation tool', author, 1), - ('dnssec-keygen', 'dnssec-keygen', 'DNSSEC key generation tool', author, 1), - ('dnssec-revoke', 'dnssec-revoke', 'set the REVOKED bit on a DNSSEC key', author, 1), - ('dnssec-settime', 'dnssec-settime', 'set the key timing metadata for a DNSSEC key', author, 1), - ('dnssec-signzone', 'dnssec-signzone', 'DNSSEC zone signing tool', author, 1), - ('dnssec-verify', 'dnssec-verify', 'DNSSEC zone verification tool', author, 1), - ('dnstap-read', 'dnstap-read', 'print dnstap data in human-readable form', author, 1), - ('filter-aaaa', 'filter-aaaa', 'filter AAAA in DNS responses when A is present', author, 8), - ('filter-a', 'filter-a', 'filter A in DNS responses when AAAA is present', author, 8), - ('host', 'host', 'DNS lookup utility', author, 1), - ('mdig', 'mdig', 'DNS pipelined lookup utility', author, 1), - ('named-checkconf', 'named-checkconf', 'named configuration file syntax checking tool', author, 1), - ('named-checkzone', 'named-checkzone', 'zone file validity checking or converting tool', author, 1), - ('named-compilezone', 'named-compilezone', 'zone file validity checking or converting tool', author, 1), - ('named-journalprint', 'named-journalprint', 'print zone journal in human-readable form', author, 1), - ('named-nzd2nzf', 'named-nzd2nzf', 'convert an NZD database to NZF text format', author, 1), - ('named-rrchecker', 'named-rrchecker', 'syntax checker for individual DNS resource records', author, 1), - ('named.conf', 'named.conf', 'configuration file for **named**', author, 5), - ('named', 'named', 'Internet domain name server', author, 8), - ('nsec3hash', 'nsec3hash', 'generate NSEC3 hash', author, 1), - ('nslookup', 'nslookup', 'query Internet name servers interactively', author, 1), - ('nsupdate', 'nsupdate', 'dynamic DNS update utility', author, 1), - ('rndc-confgen', 'rndc-confgen', 'rndc key generation tool', author, 8), - ('rndc.conf', 'rndc.conf', 'rndc configuration file', author, 5), - ('rndc', 'rndc', 'name server control utility', author, 8), - ('tsig-keygen', 'tsig-keygen', 'TSIG key generation tool', author, 8), - ] + ( + "arpaname", + "arpaname", + "translate IP addresses to the corresponding ARPA names", + author, + 1, + ), + ("ddns-confgen", "ddns-confgen", "ddns key generation tool", author, 8), + ("delv", "delv", "DNS lookup and validation utility", author, 1), + ("dig", "dig", "DNS lookup utility", author, 1), + ( + "dnssec-cds", + "dnssec-cds", + "change DS records for a child zone based on CDS/CDNSKEY", + author, + 1, + ), + ("dnssec-dsfromkey", "dnssec-dsfromkey", "DNSSEC DS RR generation tool", author, 1), + ( + "dnssec-importkey", + "dnssec-importkey", + "import DNSKEY records from external systems so they can be managed", + author, + 1, + ), + ( + "dnssec-keyfromlabel", + "dnssec-keyfromlabel", + "DNSSEC key generation tool", + author, + 1, + ), + ("dnssec-keygen", "dnssec-keygen", "DNSSEC key generation tool", author, 1), + ( + "dnssec-revoke", + "dnssec-revoke", + "set the REVOKED bit on a DNSSEC key", + author, + 1, + ), + ( + "dnssec-settime", + "dnssec-settime", + "set the key timing metadata for a DNSSEC key", + author, + 1, + ), + ("dnssec-signzone", "dnssec-signzone", "DNSSEC zone signing tool", author, 1), + ("dnssec-verify", "dnssec-verify", "DNSSEC zone verification tool", author, 1), + ( + "dnstap-read", + "dnstap-read", + "print dnstap data in human-readable form", + author, + 1, + ), + ( + "filter-aaaa", + "filter-aaaa", + "filter AAAA in DNS responses when A is present", + author, + 8, + ), + ( + "filter-a", + "filter-a", + "filter A in DNS responses when AAAA is present", + author, + 8, + ), + ("host", "host", "DNS lookup utility", author, 1), + ("mdig", "mdig", "DNS pipelined lookup utility", author, 1), + ( + "named-checkconf", + "named-checkconf", + "named configuration file syntax checking tool", + author, + 1, + ), + ( + "named-checkzone", + "named-checkzone", + "zone file validity checking or converting tool", + author, + 1, + ), + ( + "named-compilezone", + "named-compilezone", + "zone file validity checking or converting tool", + author, + 1, + ), + ( + "named-journalprint", + "named-journalprint", + "print zone journal in human-readable form", + author, + 1, + ), + ( + "named-nzd2nzf", + "named-nzd2nzf", + "convert an NZD database to NZF text format", + author, + 1, + ), + ( + "named-rrchecker", + "named-rrchecker", + "syntax checker for individual DNS resource records", + author, + 1, + ), + ("named.conf", "named.conf", "configuration file for **named**", author, 5), + ("named", "named", "Internet domain name server", author, 8), + ("nsec3hash", "nsec3hash", "generate NSEC3 hash", author, 1), + ("nslookup", "nslookup", "query Internet name servers interactively", author, 1), + ("nsupdate", "nsupdate", "dynamic DNS update utility", author, 1), + ("rndc-confgen", "rndc-confgen", "rndc key generation tool", author, 8), + ("rndc.conf", "rndc.conf", "rndc configuration file", author, 5), + ("rndc", "rndc", "name server control utility", author, 8), + ("tsig-keygen", "tsig-keygen", "TSIG key generation tool", author, 8), +] # # The rst_epilog will be completely overwritten from the Makefile, @@ -117,5 +208,6 @@ rst_epilog = """ .. |session_key| replace:: ``@runstatedir@/session.key`` """ + def setup(app): - app.add_crossref_type('iscman', 'iscman', 'pair: %s; manual page') + app.add_crossref_type("iscman", "iscman", "pair: %s; manual page") diff --git a/util/parse_tsan.py b/util/parse_tsan.py index ad4f55026c..393712a038 100755 --- a/util/parse_tsan.py +++ b/util/parse_tsan.py @@ -76,20 +76,20 @@ PATH = re.compile(TOP + "/") S = State() -with open(sys.argv[1], "r", encoding='utf-8') as f: +with open(sys.argv[1], "r", encoding="utf-8") as f: for line in f.readlines(): if line == "==================\n": if not S.inside: S.inside = True else: - DNAME = sha256(S.last_line.encode('utf-8')).hexdigest() + DNAME = sha256(S.last_line.encode("utf-8")).hexdigest() DNAME = os.path.join(OUT, DNAME) if not os.path.isdir(DNAME): os.mkdir(DNAME) - FNAME = sha256(S.block.encode('utf-8')).hexdigest() + ".txt" + FNAME = sha256(S.block.encode("utf-8")).hexdigest() + ".txt" FNAME = os.path.join(DNAME, FNAME) if not os.path.isfile(FNAME): - with open(FNAME, "w", encoding='utf-8') as w: + with open(FNAME, "w", encoding="utf-8") as w: w.write(S.block) S.reset() else: From 2a2b939f1fc0d4b405c981d1706913e988a08202 Mon Sep 17 00:00:00 2001 From: Tom Krizek Date: Tue, 7 Jun 2022 16:29:52 +0200 Subject: [PATCH 4/5] Remove flake8 linter for Python from CI Python codestyle is now handled by black and other issues are checked by pylint. Flake8 checking has been made redundant and is thus removed as obsolete. (cherry picked from commit dae340a4a518f17460e24731347a43f7179447da) --- .gitlab-ci.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4dfcfa2fff..02e3458f3f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -480,19 +480,6 @@ danger: variables: - $DANGER_GITLAB_API_TOKEN -flake8: - <<: *default_triggering_rules - <<: *base_image - stage: postcheck - needs: - - job: autoreconf - artifacts: true - script: - - *configure - - flake8 --max-line-length=80 $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/)') - # Ignore Flake8 E402 error (module level import not at top of file) in system test to enable use of pytest.importorskip - - flake8 --max-line-length=80 --extend-ignore=E402 $(git ls-files 'bin/tests/system/*.py' | grep -vE 'ans\.py') - pylint: <<: *default_triggering_rules <<: *base_image From 3f902ea9a8ff5925a2888a7cf806386c7242bec5 Mon Sep 17 00:00:00 2001 From: Tom Krizek Date: Tue, 7 Jun 2022 17:27:25 +0200 Subject: [PATCH 5/5] Move pylint CI job to precheck stage Historically, some *.py files were generated, so Python checks required running ./configure beforehand. This is no longer the case since v9_18, so let's run the job ASAP without the unnecessary extra dependency on autoconf job. (cherry picked from commit c2275d9f6edcb8ff2de386c73eb17af379b25c2a) --- .gitlab-ci.yml | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 02e3458f3f..261347c979 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -460,6 +460,14 @@ coccinelle: - util/check-cocci - if test "$(git status --porcelain | grep -Ev '\?\?' | wc -l)" -gt "0"; then git status --short; exit 1; fi +pylint: + <<: *precheck_job + needs: [] + script: + - pylint --rcfile $CI_PROJECT_DIR/.pylintrc $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/)') + # Ignore Pylint wrong-import-position error in system test to enable use of pytest.importorskip + - pylint --rcfile $CI_PROJECT_DIR/.pylintrc --disable=wrong-import-position $(git ls-files 'bin/tests/system/*.py' | grep -vE 'ans\.py') + reuse: <<: *precheck_job needs: [] @@ -480,19 +488,6 @@ danger: variables: - $DANGER_GITLAB_API_TOKEN -pylint: - <<: *default_triggering_rules - <<: *base_image - stage: postcheck - needs: - - job: autoreconf - artifacts: true - script: - - *configure - - pylint --rcfile $CI_PROJECT_DIR/.pylintrc $(git ls-files '*.py' | grep -vE '(ans\.py|dangerfile\.py|^bin/tests/system/)') - # Ignore Pylint wrong-import-position error in system test to enable use of pytest.importorskip - - pylint --rcfile $CI_PROJECT_DIR/.pylintrc --disable=wrong-import-position $(git ls-files 'bin/tests/system/*.py' | grep -vE 'ans\.py') - tarball-create: stage: precheck <<: *base_image