mirror of
https://github.com/oskar456/dzonegit.git
synced 2024-05-11 05:55:41 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17cbd099de | ||
|
|
d809e24172 | ||
|
|
35d01a796e | ||
|
|
2f7776c0d1 | ||
|
|
498d4a8b82 | ||
|
|
a96597decb | ||
|
|
8f952086aa | ||
|
|
83a4049821 | ||
|
|
15cdae67ee | ||
|
|
12fb932711 | ||
|
|
cb543514ac | ||
|
|
f9c6a52357 | ||
|
|
24d992d999 | ||
|
|
7cb7c42d76 | ||
|
|
3dd346294a | ||
|
|
03fde74ede | ||
|
|
3769dd22fb | ||
|
|
8d15bb531c | ||
|
|
e2e4a3daf7 | ||
|
|
4efef8be9e | ||
|
|
ef059861b7 | ||
|
|
94461383e8 | ||
|
|
3e09833ec1 | ||
|
|
9ad1e74a88 | ||
|
|
a7d693253d | ||
|
|
3777453d2f | ||
|
|
023906177a | ||
|
|
e79bb901f3 | ||
|
|
f07c84aa32 |
42
.github/workflows/python-test.yml
vendored
Normal file
42
.github/workflows/python-test.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||||
|
|
||||||
|
name: Python package
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
python-version: [3.6, 3.7, 3.8, 3.9]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Instal BIND 9 utils
|
||||||
|
run: sudo apt-get install -y bind9utils
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install flake8 pytest
|
||||||
|
python -m pip install -e .
|
||||||
|
- name: Lint with flake8
|
||||||
|
run: |
|
||||||
|
# stop the build if there are Python syntax errors or undefined names
|
||||||
|
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||||
|
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||||
|
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||||
|
- name: Test with pytest
|
||||||
|
run: |
|
||||||
|
pytest
|
||||||
16
.travis.yml
16
.travis.yml
@@ -1,16 +0,0 @@
|
|||||||
before_install:
|
|
||||||
- sudo apt-get install -y bind9utils
|
|
||||||
language: python
|
|
||||||
python:
|
|
||||||
- "3.5"
|
|
||||||
- "3.6"
|
|
||||||
- "nightly"
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- python: "nightly"
|
|
||||||
install:
|
|
||||||
- pip install -e .
|
|
||||||
- pip install pytest
|
|
||||||
script:
|
|
||||||
- pytest
|
|
||||||
sudo: false
|
|
||||||
20
README.rst
20
README.rst
@@ -1,3 +1,6 @@
|
|||||||
|
.. image:: https://travis-ci.org/oskar456/dzonegit.svg?branch=master
|
||||||
|
:target: https://travis-ci.org/oskar456/dzonegit
|
||||||
|
|
||||||
Git hooks to manage a repository of DNS zones
|
Git hooks to manage a repository of DNS zones
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
@@ -59,24 +62,22 @@ Support for $UNIXTIME directive
|
|||||||
|
|
||||||
If you want to use ``$UNIXTIME`` in your zone files instead of serial number,
|
If you want to use ``$UNIXTIME`` in your zone files instead of serial number,
|
||||||
you have to install a `smudge` filter on the server, that will replace the
|
you have to install a `smudge` filter on the server, that will replace the
|
||||||
directive with current unix time on checkout. First, set up the filter in
|
directive with current unix time on every checkout. First, set up the filter
|
||||||
the Git configuration:
|
in the Git configuration:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
$ git config --global filter.dzonegit.smudge $(which dzonegit-smudge-serial)
|
$ git config --global filter.dzonegit.smudge $(which dzonegit-smudge-serial)
|
||||||
$ git config --global filter.dzonegit.clean cat
|
|
||||||
|
|
||||||
|
|
||||||
Then, apply the filter on all zone files using ``.gitattributes`` file inside
|
Then, apply the filter on all zone files using either ``.git/info/attributes``
|
||||||
the repository:
|
or directly ``.gitattributes`` file inside the repository:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
*.zone filter=dzonegit
|
*.zone filter=dzonegit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Configuration options
|
Configuration options
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -95,6 +96,10 @@ named ``dzonegit``. All boolean options default to *False*.
|
|||||||
Do not try to automatically update zone serial number if necessary.
|
Do not try to automatically update zone serial number if necessary.
|
||||||
Valid only in the ``pre-commit`` hook.
|
Valid only in the ``pre-commit`` hook.
|
||||||
|
|
||||||
|
*dzonegit.nomissingdotcheck*
|
||||||
|
Do not check for forgotten final dot on the right-hand side of PTR records.
|
||||||
|
Valid only in the ``pre-commit`` hook.
|
||||||
|
|
||||||
*dzonegit.checkoutpath*
|
*dzonegit.checkoutpath*
|
||||||
Path to a writable directory, to which ``post-receive`` hook checks out
|
Path to a writable directory, to which ``post-receive`` hook checks out
|
||||||
current *HEAD* after each update.
|
current *HEAD* after each update.
|
||||||
@@ -178,6 +183,9 @@ In the template strings, these placeholders are supported:
|
|||||||
``$zonefile``
|
``$zonefile``
|
||||||
Full path to the zone file
|
Full path to the zone file
|
||||||
|
|
||||||
|
``$zonerelfile``
|
||||||
|
Path to the zone file, relative to checkout path (useful for chroot environments)
|
||||||
|
|
||||||
``$zonevar``
|
``$zonevar``
|
||||||
Per-zone specific variable, see above
|
Per-zone specific variable, see above
|
||||||
|
|
||||||
|
|||||||
101
dzonegit.py
101
dzonegit.py
@@ -41,24 +41,24 @@ class HookException(ValueError):
|
|||||||
return "".join(r)
|
return "".join(r)
|
||||||
|
|
||||||
|
|
||||||
def get_head():
|
def get_head(empty=False):
|
||||||
r = subprocess.run(
|
if not empty:
|
||||||
["git", "rev-parse", "--verify", "HEAD"],
|
r = subprocess.run(
|
||||||
stdout=subprocess.PIPE,
|
["git", "rev-parse", "--verify", "HEAD"],
|
||||||
stderr=subprocess.DEVNULL,
|
stdout=subprocess.PIPE,
|
||||||
)
|
stderr=subprocess.DEVNULL,
|
||||||
if r.returncode == 0:
|
)
|
||||||
return r.stdout.decode("utf-8").strip()
|
if r.returncode == 0:
|
||||||
else:
|
return r.stdout.decode("ascii").strip()
|
||||||
# Initial commit: diff against an empty tree object
|
# Initial commit: diff against an empty tree object
|
||||||
return "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
return "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
||||||
|
|
||||||
|
|
||||||
def check_whitespace_errors(against, revision=None):
|
def check_whitespace_errors(against, revision=None):
|
||||||
if revision:
|
if revision:
|
||||||
cmd = ["git", "diff-tree", "--check", against, revision]
|
cmd = ["git", "diff-tree", "--check", against, revision, "*.zone"]
|
||||||
else:
|
else:
|
||||||
cmd = ["git", "diff-index", "--check", "--cached", against]
|
cmd = ["git", "diff-index", "--check", "--cached", against, "*.zone"]
|
||||||
r = subprocess.run(
|
r = subprocess.run(
|
||||||
cmd,
|
cmd,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
@@ -95,13 +95,31 @@ def unixtime_directive(zonedata, unixtime=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def compile_zone(zonename, zonedata, unixtime=None):
|
def check_missing_trailing_dot(zonename, compiled_zonedata):
|
||||||
|
badlines = []
|
||||||
|
for line in compiled_zonedata.splitlines():
|
||||||
|
if re.search(
|
||||||
|
r"\sPTR\s+[^\s]*\.{}.$".format(zonename).encode("ascii"),
|
||||||
|
line,
|
||||||
|
re.I,
|
||||||
|
):
|
||||||
|
badlines.append(line.decode("utf-8"))
|
||||||
|
if badlines:
|
||||||
|
raise HookException(
|
||||||
|
"Possibly missing trailing dot after PTR records:\n{}".format(
|
||||||
|
"\n".join(badlines),
|
||||||
|
),
|
||||||
|
fname=zonename,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def compile_zone(zonename, zonedata, unixtime=None, missing_dot=False):
|
||||||
""" Compile the zone. Return tuple with results."""
|
""" Compile the zone. Return tuple with results."""
|
||||||
CompileResults = namedtuple(
|
CompileResults = namedtuple(
|
||||||
"CompileResults", "success, serial, zonehash, stderr",
|
"CompileResults", "success, serial, zonehash, stderr",
|
||||||
)
|
)
|
||||||
r = subprocess.run(
|
r = subprocess.run(
|
||||||
["/usr/sbin/named-compilezone", "-o", "-", zonename, "/dev/stdin"],
|
["/usr/bin/env", "named-compilezone", "-o", "-", zonename, "/dev/stdin"],
|
||||||
input=unixtime_directive(zonedata, unixtime),
|
input=unixtime_directive(zonedata, unixtime),
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
@@ -110,6 +128,8 @@ def compile_zone(zonename, zonedata, unixtime=None):
|
|||||||
m = re.search(r"^zone.*loaded serial ([0-9]*)$", stderr, re.MULTILINE)
|
m = re.search(r"^zone.*loaded serial ([0-9]*)$", stderr, re.MULTILINE)
|
||||||
if r.returncode == 0 and m:
|
if r.returncode == 0 and m:
|
||||||
serial = m.group(1)
|
serial = m.group(1)
|
||||||
|
if missing_dot:
|
||||||
|
check_missing_trailing_dot(zonename, r.stdout)
|
||||||
zonehash = sha256(r.stdout).hexdigest()
|
zonehash = sha256(r.stdout).hexdigest()
|
||||||
return CompileResults(True, serial, zonehash, stderr)
|
return CompileResults(True, serial, zonehash, stderr)
|
||||||
else:
|
else:
|
||||||
@@ -146,7 +166,7 @@ def get_altered_files(against, diff_filter=None, revision=None):
|
|||||||
If revision is None, list changes between staging area and
|
If revision is None, list changes between staging area and
|
||||||
revision. Otherwise differences between two revisions are computed.
|
revision. Otherwise differences between two revisions are computed.
|
||||||
"""
|
"""
|
||||||
cmd = ["git", "diff", "--name-only", "-z"]
|
cmd = ["git", "diff", "--name-only", "-z", "--no-renames"]
|
||||||
if diff_filter:
|
if diff_filter:
|
||||||
cmd.append("--diff-filter={}".format(diff_filter))
|
cmd.append("--diff-filter={}".format(diff_filter))
|
||||||
if revision:
|
if revision:
|
||||||
@@ -203,7 +223,12 @@ def get_zone_name(path, zonedata):
|
|||||||
return stemname
|
return stemname
|
||||||
|
|
||||||
|
|
||||||
def check_updated_zones(against, revision=None, autoupdate_serial=False):
|
def check_updated_zones(
|
||||||
|
against,
|
||||||
|
revision=None,
|
||||||
|
autoupdate_serial=False,
|
||||||
|
missing_dot=False,
|
||||||
|
):
|
||||||
""" Check whether all updated zone files compile. """
|
""" Check whether all updated zone files compile. """
|
||||||
unixtime = int(time.time())
|
unixtime = int(time.time())
|
||||||
for f in get_altered_files(against, "AMCR", revision):
|
for f in get_altered_files(against, "AMCR", revision):
|
||||||
@@ -212,7 +237,7 @@ def check_updated_zones(against, revision=None, autoupdate_serial=False):
|
|||||||
print("Checking file {f}".format(f=f))
|
print("Checking file {f}".format(f=f))
|
||||||
zonedata = get_file_contents(f, revision)
|
zonedata = get_file_contents(f, revision)
|
||||||
zname = get_zone_name(f, zonedata)
|
zname = get_zone_name(f, zonedata)
|
||||||
rnew = compile_zone(zname, zonedata, unixtime)
|
rnew = compile_zone(zname, zonedata, unixtime, missing_dot)
|
||||||
if not rnew.success:
|
if not rnew.success:
|
||||||
raise HookException(
|
raise HookException(
|
||||||
"New zone version does not compile",
|
"New zone version does not compile",
|
||||||
@@ -232,9 +257,11 @@ def check_updated_zones(against, revision=None, autoupdate_serial=False):
|
|||||||
|
|
||||||
if autoupdate_serial:
|
if autoupdate_serial:
|
||||||
newserial = get_increased_serial(rnew.serial)
|
newserial = get_increased_serial(rnew.serial)
|
||||||
replace_serial(f, rnew.serial, newserial)
|
if replace_serial(f, rnew.serial, newserial):
|
||||||
errmsg += " Serial has been automatically increased."
|
errmsg += " Serial has been automatically increased."
|
||||||
errmsg += " Check and recommit."
|
errmsg += " Check and recommit."
|
||||||
|
else:
|
||||||
|
errmsg += " Autoupdate of serial number failed."
|
||||||
raise HookException(
|
raise HookException(
|
||||||
errmsg,
|
errmsg,
|
||||||
fname=f,
|
fname=f,
|
||||||
@@ -277,8 +304,9 @@ def replace_serial(path, oldserial, newserial):
|
|||||||
flags=re.DOTALL | re.IGNORECASE | re.MULTILINE,
|
flags=re.DOTALL | re.IGNORECASE | re.MULTILINE,
|
||||||
)
|
)
|
||||||
if count != 1:
|
if count != 1:
|
||||||
raise HookException("Cannot update zone serial number")
|
return False
|
||||||
path.write_text(updated)
|
path.write_text(updated)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def get_zone_wildcards(name):
|
def get_zone_wildcards(name):
|
||||||
@@ -330,7 +358,8 @@ def template_config(checkoutpath, template, blacklist=set(), whitelist=set()):
|
|||||||
out = list()
|
out = list()
|
||||||
zones = dict()
|
zones = dict()
|
||||||
mapping = {"datetime": datetime.datetime.now().strftime("%c")}
|
mapping = {"datetime": datetime.datetime.now().strftime("%c")}
|
||||||
out.append(headertpl.substitute(mapping))
|
if headertpl.template:
|
||||||
|
out.append(headertpl.substitute(mapping))
|
||||||
for f in sorted(Path(checkoutpath).glob("**/*.zone")):
|
for f in sorted(Path(checkoutpath).glob("**/*.zone")):
|
||||||
zonename = get_zone_name(f, f.read_bytes())
|
zonename = get_zone_name(f, f.read_bytes())
|
||||||
if whitelist and not any(
|
if whitelist and not any(
|
||||||
@@ -366,9 +395,10 @@ def template_config(checkoutpath, template, blacklist=set(), whitelist=set()):
|
|||||||
zonevar = defaultvar
|
zonevar = defaultvar
|
||||||
out.append(itemtpl.substitute(
|
out.append(itemtpl.substitute(
|
||||||
mapping, zonename=zonename,
|
mapping, zonename=zonename,
|
||||||
zonefile=str(f), zonevar=zonevar,
|
zonefile=str(f), zonerelfile=str(f.relative_to(checkoutpath)), zonevar=zonevar,
|
||||||
))
|
))
|
||||||
out.append(footertpl.substitute(mapping))
|
if footertpl.template:
|
||||||
|
out.append(footertpl.substitute(mapping))
|
||||||
return "\n".join(out)
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
@@ -382,13 +412,19 @@ def load_set_file(path):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def do_commit_checks(against, revision=None, autoupdate_serial=False):
|
def do_commit_checks(
|
||||||
|
against,
|
||||||
|
revision=None,
|
||||||
|
autoupdate_serial=False,
|
||||||
|
missing_dot=False,
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
if not get_config("dzonegit.ignorewhitespaceerrors", bool):
|
if not get_config("dzonegit.ignorewhitespaceerrors", bool):
|
||||||
check_whitespace_errors(against, revision=revision)
|
check_whitespace_errors(against, revision=revision)
|
||||||
check_updated_zones(
|
check_updated_zones(
|
||||||
against, revision=revision,
|
against, revision=revision,
|
||||||
autoupdate_serial=autoupdate_serial,
|
autoupdate_serial=autoupdate_serial,
|
||||||
|
missing_dot=missing_dot,
|
||||||
)
|
)
|
||||||
except HookException as e:
|
except HookException as e:
|
||||||
print(e)
|
print(e)
|
||||||
@@ -398,7 +434,12 @@ def do_commit_checks(against, revision=None, autoupdate_serial=False):
|
|||||||
def pre_commit():
|
def pre_commit():
|
||||||
against = get_head()
|
against = get_head()
|
||||||
autoupdate_serial = not get_config("dzonegit.noserialupdate", bool)
|
autoupdate_serial = not get_config("dzonegit.noserialupdate", bool)
|
||||||
do_commit_checks(against, autoupdate_serial=autoupdate_serial)
|
missing_dot = not get_config("dzonegit.nomissingdotcheck", bool)
|
||||||
|
do_commit_checks(
|
||||||
|
against,
|
||||||
|
autoupdate_serial=autoupdate_serial,
|
||||||
|
missing_dot=missing_dot,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def update(argv=sys.argv):
|
def update(argv=sys.argv):
|
||||||
@@ -411,7 +452,7 @@ def update(argv=sys.argv):
|
|||||||
refname, against, revision = argv[1:4]
|
refname, against, revision = argv[1:4]
|
||||||
|
|
||||||
if against == "0000000000000000000000000000000000000000":
|
if against == "0000000000000000000000000000000000000000":
|
||||||
against = get_head() # Empty commit
|
against = get_head(True) # Empty commit
|
||||||
|
|
||||||
if refname != "refs/heads/master":
|
if refname != "refs/heads/master":
|
||||||
raise SystemExit("Nothing else than master branch is accepted here")
|
raise SystemExit("Nothing else than master branch is accepted here")
|
||||||
@@ -429,7 +470,7 @@ def pre_receive(stdin=sys.stdin):
|
|||||||
"is accepted here",
|
"is accepted here",
|
||||||
)
|
)
|
||||||
if against == "0000000000000000000000000000000000000000":
|
if against == "0000000000000000000000000000000000000000":
|
||||||
against = get_head() # Empty commit
|
against = get_head(True) # Empty commit
|
||||||
do_commit_checks(against, revision)
|
do_commit_checks(against, revision)
|
||||||
|
|
||||||
|
|
||||||
@@ -479,7 +520,7 @@ def post_receive(stdin=sys.stdin):
|
|||||||
if refname != "refs/heads/master":
|
if refname != "refs/heads/master":
|
||||||
continue
|
continue
|
||||||
if against == "0000000000000000000000000000000000000000":
|
if against == "0000000000000000000000000000000000000000":
|
||||||
against = get_head() # Empty commit
|
against = get_head(True) # Empty commit
|
||||||
should_reconfig = [
|
should_reconfig = [
|
||||||
f for f in get_altered_files(against, "ACDRU", revision)
|
f for f in get_altered_files(against, "ACDRU", revision)
|
||||||
if f.suffix == ".zone"
|
if f.suffix == ".zone"
|
||||||
|
|||||||
4
setup.py
4
setup.py
@@ -5,7 +5,7 @@ readme = Path(__file__).with_name("README.rst").read_text()
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="dzonegit",
|
name="dzonegit",
|
||||||
version="0.6",
|
version="0.15",
|
||||||
description="Git hooks to manage a repository of DNS zones",
|
description="Git hooks to manage a repository of DNS zones",
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
long_description_content_type="text/x-rst",
|
long_description_content_type="text/x-rst",
|
||||||
@@ -27,7 +27,7 @@ setup(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Development Status :: 3 - Alpha",
|
"Development Status :: 4 - Beta",
|
||||||
"Environment :: Console",
|
"Environment :: Console",
|
||||||
"Intended Audience :: System Administrators",
|
"Intended Audience :: System Administrators",
|
||||||
"License :: OSI Approved :: MIT License",
|
"License :: OSI Approved :: MIT License",
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ def git_dir(tmpdir_factory):
|
|||||||
d = tmpdir_factory.getbasetemp()
|
d = tmpdir_factory.getbasetemp()
|
||||||
d.chdir()
|
d.chdir()
|
||||||
subprocess.call(["git", "init"])
|
subprocess.call(["git", "init"])
|
||||||
|
subprocess.call(["git", "config", "user.name", "dzonegit pytest"])
|
||||||
|
subprocess.call(["git", "config", "user.email", "nonexistent@example.com"])
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
@@ -25,18 +27,22 @@ def test_get_head(git_dir):
|
|||||||
subprocess.call(["git", "add", "dummy"])
|
subprocess.call(["git", "add", "dummy"])
|
||||||
subprocess.call(["git", "commit", "-m", "dummy"])
|
subprocess.call(["git", "commit", "-m", "dummy"])
|
||||||
assert dzonegit.get_head() != "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
assert dzonegit.get_head() != "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
|
||||||
|
subprocess.call(["git", "update-ref", "-d", "HEAD"])
|
||||||
|
|
||||||
|
|
||||||
def test_check_whitespace_errors(git_dir):
|
def test_check_whitespace_errors(git_dir):
|
||||||
git_dir.chdir()
|
git_dir.chdir()
|
||||||
git_dir.join("whitespace").write(" ")
|
git_dir.join("whitespace").write(" ")
|
||||||
subprocess.call(["git", "add", "whitespace"])
|
subprocess.call(["git", "add", "whitespace"])
|
||||||
|
dzonegit.check_whitespace_errors(dzonegit.get_head())
|
||||||
|
git_dir.join("whitespace.zone").write(" ")
|
||||||
|
subprocess.call(["git", "add", "whitespace.zone"])
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
dzonegit.check_whitespace_errors(dzonegit.get_head())
|
dzonegit.check_whitespace_errors(dzonegit.get_head())
|
||||||
subprocess.call(["git", "commit", "-m", "whitespace"])
|
subprocess.call(["git", "commit", "-m", "whitespace"])
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
dzonegit.check_whitespace_errors("HEAD~", dzonegit.get_head())
|
dzonegit.check_whitespace_errors("HEAD~", dzonegit.get_head())
|
||||||
subprocess.call(["git", "rm", "-f", "whitespace"])
|
subprocess.call(["git", "rm", "-f", "whitespace*"])
|
||||||
subprocess.call(["git", "commit", "-m", "rm whitespace"])
|
subprocess.call(["git", "commit", "-m", "rm whitespace"])
|
||||||
dzonegit.check_whitespace_errors(dzonegit.get_head())
|
dzonegit.check_whitespace_errors(dzonegit.get_head())
|
||||||
dzonegit.check_whitespace_errors("HEAD~", dzonegit.get_head())
|
dzonegit.check_whitespace_errors("HEAD~", dzonegit.get_head())
|
||||||
@@ -62,16 +68,20 @@ $ORIGIN example.com.
|
|||||||
60 IN NS ns
|
60 IN NS ns
|
||||||
ns.example.com. 60 IN A 192.0.2.1
|
ns.example.com. 60 IN A 192.0.2.1
|
||||||
"""
|
"""
|
||||||
r = dzonegit.compile_zone("example.org", testzone)
|
r = dzonegit.compile_zone("example.org", testzone, missing_dot=True)
|
||||||
assert not r.success
|
assert not r.success
|
||||||
assert r.zonehash is None
|
assert r.zonehash is None
|
||||||
assert r.stderr
|
assert r.stderr
|
||||||
r = dzonegit.compile_zone("example.com", testzone)
|
r = dzonegit.compile_zone("example.com", testzone, missing_dot=True)
|
||||||
assert r.success
|
assert r.success
|
||||||
assert r.serial == "1234567890"
|
assert r.serial == "1234567890"
|
||||||
assert r.zonehash
|
assert r.zonehash
|
||||||
r2 = dzonegit.compile_zone("example.com", testzone + b"\n\n; some comment")
|
r2 = dzonegit.compile_zone("example.com", testzone + b"\n\n; some comment")
|
||||||
assert r.zonehash == r2.zonehash
|
assert r.zonehash == r2.zonehash
|
||||||
|
testzone += b"1 60 IN PTR www\n"
|
||||||
|
dzonegit.compile_zone("example.com", testzone, missing_dot=False)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
dzonegit.compile_zone("example.com", testzone, missing_dot=True)
|
||||||
|
|
||||||
|
|
||||||
def test_compile_unsmudged_zone():
|
def test_compile_unsmudged_zone():
|
||||||
@@ -118,7 +128,7 @@ def test_get_altered_files(git_dir):
|
|||||||
assert files == {Path("dummy"), Path("new")}
|
assert files == {Path("dummy"), Path("new")}
|
||||||
# Refers to test_check_whitespace_errors
|
# Refers to test_check_whitespace_errors
|
||||||
files = set(dzonegit.get_altered_files("HEAD~", "D", "HEAD"))
|
files = set(dzonegit.get_altered_files("HEAD~", "D", "HEAD"))
|
||||||
assert files == {Path("whitespace")}
|
assert files == {Path("whitespace"), Path("whitespace.zone")}
|
||||||
subprocess.call(["git", "checkout", "-f", "HEAD"])
|
subprocess.call(["git", "checkout", "-f", "HEAD"])
|
||||||
assert set(dzonegit.get_altered_files("HEAD", "AM")) == set()
|
assert set(dzonegit.get_altered_files("HEAD", "AM")) == set()
|
||||||
|
|
||||||
@@ -150,6 +160,7 @@ $ORIGIN eXample.com. ;coment
|
|||||||
60 IN NS ns
|
60 IN NS ns
|
||||||
ns.example.com. 60 IN A 192.0.2.1
|
ns.example.com. 60 IN A 192.0.2.1
|
||||||
"""
|
"""
|
||||||
|
subprocess.call(["git", "config", "dzonegit.allowfancynames", "FALSE"])
|
||||||
assert "example.com" == dzonegit.get_zone_name(
|
assert "example.com" == dzonegit.get_zone_name(
|
||||||
"zones/example.com.zone", "",
|
"zones/example.com.zone", "",
|
||||||
)
|
)
|
||||||
@@ -177,12 +188,12 @@ def test_replace_serial(git_dir):
|
|||||||
@ 60 IN SOA ns hm 1 61 60 60 60
|
@ 60 IN SOA ns hm 1 61 60 60 60
|
||||||
60 NS ns.example.org.
|
60 NS ns.example.org.
|
||||||
""")
|
""")
|
||||||
dzonegit.replace_serial(Path("dummy.zone"), "1", "60")
|
assert dzonegit.replace_serial(Path("dummy.zone"), "1", "60")
|
||||||
assert git_dir.join("dummy.zone").read() == """
|
assert git_dir.join("dummy.zone").read() == """
|
||||||
@ 60 IN SOA ns hm 60 61 60 60 60
|
@ 60 IN SOA ns hm 60 61 60 60 60
|
||||||
60 NS ns.example.org.
|
60 NS ns.example.org.
|
||||||
"""
|
"""
|
||||||
dzonegit.replace_serial(Path("dummy.zone"), "60", "61")
|
assert dzonegit.replace_serial(Path("dummy.zone"), "60", "61")
|
||||||
assert git_dir.join("dummy.zone").read() == """
|
assert git_dir.join("dummy.zone").read() == """
|
||||||
@ 60 IN SOA ns hm 61 61 60 60 60
|
@ 60 IN SOA ns hm 61 61 60 60 60
|
||||||
60 NS ns.example.org.
|
60 NS ns.example.org.
|
||||||
@@ -197,7 +208,7 @@ def test_replace_serial(git_dir):
|
|||||||
)
|
)
|
||||||
60 NS ns.example.org.
|
60 NS ns.example.org.
|
||||||
""")
|
""")
|
||||||
dzonegit.replace_serial(Path("dummy.zone"), "60", "6000000")
|
assert dzonegit.replace_serial(Path("dummy.zone"), "60", "6000000")
|
||||||
assert git_dir.join("dummy.zone").read() == """
|
assert git_dir.join("dummy.zone").read() == """
|
||||||
@ 60 IN SOA ns hm (
|
@ 60 IN SOA ns hm (
|
||||||
6000000 ; serial
|
6000000 ; serial
|
||||||
@@ -208,6 +219,7 @@ def test_replace_serial(git_dir):
|
|||||||
)
|
)
|
||||||
60 NS ns.example.org.
|
60 NS ns.example.org.
|
||||||
"""
|
"""
|
||||||
|
assert not dzonegit.replace_serial(Path("dummy.zone"), "0", "60")
|
||||||
|
|
||||||
|
|
||||||
def test_check_updated_zones(git_dir):
|
def test_check_updated_zones(git_dir):
|
||||||
@@ -328,7 +340,7 @@ def test_post_receive(git_dir):
|
|||||||
git_dir.chdir()
|
git_dir.chdir()
|
||||||
head = dzonegit.get_head()
|
head = dzonegit.get_head()
|
||||||
revisions = "{} {} refs/heads/master\n".format(
|
revisions = "{} {} refs/heads/master\n".format(
|
||||||
"4b825dc642cb6eb9a060e54bf8d69288fbee4904",
|
"0000000000000000000000000000000000000000",
|
||||||
head,
|
head,
|
||||||
)
|
)
|
||||||
stdin = StringIO(revisions)
|
stdin = StringIO(revisions)
|
||||||
@@ -339,9 +351,19 @@ def test_post_receive(git_dir):
|
|||||||
"echo TEST >{}/test".format(codir),
|
"echo TEST >{}/test".format(codir),
|
||||||
])
|
])
|
||||||
dzonegit.post_receive(stdin)
|
dzonegit.post_receive(stdin)
|
||||||
dzonegit.post_receive(stdin) # Check coping with existing codir
|
|
||||||
assert codir.join("dummy.zone").check()
|
assert codir.join("dummy.zone").check()
|
||||||
assert codir.join("test").read() == "TEST\n"
|
assert codir.join("test").read() == "TEST\n"
|
||||||
|
# Test reconfig after renaming the file
|
||||||
|
codir.join("test").write("")
|
||||||
|
subprocess.call(["git", "mv", "dummy.zone", "dummy.zone.old"])
|
||||||
|
subprocess.call(["git", "commit", "-m", "rename dummy zone"])
|
||||||
|
revisions = "{} {} refs/heads/master\n".format(
|
||||||
|
head,
|
||||||
|
dzonegit.get_head(),
|
||||||
|
)
|
||||||
|
stdin = StringIO(revisions)
|
||||||
|
dzonegit.post_receive(stdin)
|
||||||
|
assert codir.join("test").read() == "TEST\n"
|
||||||
|
|
||||||
|
|
||||||
def test_template_config(git_dir):
|
def test_template_config(git_dir):
|
||||||
@@ -372,6 +394,8 @@ def test_template_config(git_dir):
|
|||||||
blacklist=set("*"),
|
blacklist=set("*"),
|
||||||
)
|
)
|
||||||
assert " - zone: \"dummy\"\n file: \"" not in output
|
assert " - zone: \"dummy\"\n file: \"" not in output
|
||||||
|
output = dzonegit.template_config(str(git_dir), "{}")
|
||||||
|
assert len(output) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_load_set_file(git_dir):
|
def test_load_set_file(git_dir):
|
||||||
@@ -385,3 +409,10 @@ def test_get_zone_wildcards():
|
|||||||
"a.long.zone.name", "*.long.zone.name",
|
"a.long.zone.name", "*.long.zone.name",
|
||||||
"*.zone.name", "*.name", "*",
|
"*.zone.name", "*.name", "*",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_trailing_dot():
|
||||||
|
zonename = "example.com"
|
||||||
|
zonedata = b"something.example.com. IN PTR s.example.com."
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
dzonegit.check_missing_trailing_dot(zonename, zonedata)
|
||||||
|
|||||||
Reference in New Issue
Block a user