mirror of
https://github.com/oskar456/dzonegit.git
synced 2024-05-11 05:55:41 +00:00
Add config template generator
This commit is contained in:
72
dzonegit.py
72
dzonegit.py
@ -6,9 +6,11 @@ import subprocess
|
|||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from string import Template
|
||||||
|
|
||||||
|
|
||||||
class HookException(ValueError):
|
class HookException(ValueError):
|
||||||
@ -265,6 +267,51 @@ def replace_serial(path, oldserial, newserial):
|
|||||||
path.write_text(updated)
|
path.write_text(updated)
|
||||||
|
|
||||||
|
|
||||||
|
def template_config(checkoutpath, template):
|
||||||
|
""" Recursively find all *.zone files and template config file using
|
||||||
|
a simple JSON based template like this:
|
||||||
|
|
||||||
|
{
|
||||||
|
"header": "# Managed by dzonegit, do not edit.\n",
|
||||||
|
"footer": "",
|
||||||
|
"item": " - zone: \"$zonename\"\n file: \"$zonefile\"\n $zonevar\n",
|
||||||
|
"defaultvar": "template: default",
|
||||||
|
"zonevars": {
|
||||||
|
"example.com": "template: signed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Available placeholders are:
|
||||||
|
- $datetime - timestamp of file creation
|
||||||
|
- $zonename - zone name, without trailing dot
|
||||||
|
- $zonefile - full path to zone file
|
||||||
|
- $zonevar - per-zone specific variables, content of `defaultvar` if
|
||||||
|
not defined for current zone
|
||||||
|
"""
|
||||||
|
tpl = json.loads(template)
|
||||||
|
headertpl = Template(tpl.get("header", ""))
|
||||||
|
footertpl = Template(tpl.get("footer", ""))
|
||||||
|
itemtpl = Template(tpl.get("item", ""))
|
||||||
|
defaultvar = tpl.get("defaultvar", "")
|
||||||
|
zonevars = tpl.get("zonevars", dict())
|
||||||
|
out = list()
|
||||||
|
zones = set()
|
||||||
|
mapping = {"datetime": datetime.datetime.now().strftime("%c")}
|
||||||
|
out.append(headertpl.substitute(mapping))
|
||||||
|
for f in Path(checkoutpath).glob("**/*.zone"):
|
||||||
|
zonename = get_zone_name(f, f.read_bytes())
|
||||||
|
if zonename in zones:
|
||||||
|
continue # Safety net in case duplicate zone file is found
|
||||||
|
zones.add(zonename)
|
||||||
|
zonevar = zonevars[zonename] if zonename in zonevars else defaultvar
|
||||||
|
out.append(itemtpl.substitute(
|
||||||
|
mapping, zonename=zonename,
|
||||||
|
zonefile=str(f), zonevar=zonevar,
|
||||||
|
))
|
||||||
|
out.append(footertpl.substitute(mapping))
|
||||||
|
return "\n".join(out)
|
||||||
|
|
||||||
|
|
||||||
def do_commit_checks(against, revision=None, autoupdate_serial=False):
|
def do_commit_checks(against, revision=None, autoupdate_serial=False):
|
||||||
try:
|
try:
|
||||||
if not get_config("dzonegit.ignorewhitespaceerrors", bool):
|
if not get_config("dzonegit.ignorewhitespaceerrors", bool):
|
||||||
@ -323,16 +370,23 @@ def post_receive(stdin=sys.stdin):
|
|||||||
added or delefed.
|
added or delefed.
|
||||||
"""
|
"""
|
||||||
suffixes = list(str(n) if n else "" for n in range(10))
|
suffixes = list(str(n) if n else "" for n in range(10))
|
||||||
for s in suffixes:
|
checkoutpath = get_config("dzonegit.checkoutpath")
|
||||||
d = get_config("dzonegit.checkoutpath{}".format(s))
|
if checkoutpath:
|
||||||
if d:
|
print("Checking out repository into {}…".format(checkoutpath))
|
||||||
print("Checking out repository into {}…".format(d))
|
subprocess.run(
|
||||||
subprocess.run(
|
["git", "checkout", "-f", "master"],
|
||||||
["git", "checkout", "-f", "master"],
|
check=True,
|
||||||
check=True,
|
env=dict(os.environ, GIT_WORK_TREE=checkoutpath),
|
||||||
env=dict(os.environ, GIT_WORK_TREE=d),
|
)
|
||||||
|
for s in suffixes:
|
||||||
|
cfpath = get_config("dzonegit.conffilepath{}".format(s))
|
||||||
|
tplpath = get_config("dzonegit.conffiletemplate{}".format(s))
|
||||||
|
if cfpath is None or tplpath is None:
|
||||||
|
continue
|
||||||
|
print("Templating config file {}…".format(cfpath))
|
||||||
|
Path(cfpath).write_text(
|
||||||
|
template_config(checkoutpath, Path(tplpath).read_text()),
|
||||||
)
|
)
|
||||||
# TODO config
|
|
||||||
|
|
||||||
if stdin.isatty():
|
if stdin.isatty():
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
|
@ -273,10 +273,23 @@ def test_post_receive(git_dir):
|
|||||||
git_dir.chdir()
|
git_dir.chdir()
|
||||||
revisions = "{} {} ".format("0"*40, dzonegit.get_head())
|
revisions = "{} {} ".format("0"*40, dzonegit.get_head())
|
||||||
stdin = StringIO(revisions + "refs/heads/master\n")
|
stdin = StringIO(revisions + "refs/heads/master\n")
|
||||||
codir1 = git_dir.mkdir("co1")
|
codir = git_dir.mkdir("co")
|
||||||
codir2 = git_dir.mkdir("co2")
|
subprocess.call(["git", "config", "dzonegit.checkoutpath", str(codir)])
|
||||||
subprocess.call(["git", "config", "dzonegit.checkoutpath", str(codir1)])
|
|
||||||
subprocess.call(["git", "config", "dzonegit.checkoutpath9", str(codir2)])
|
|
||||||
dzonegit.post_receive(stdin)
|
dzonegit.post_receive(stdin)
|
||||||
assert codir1.join("dummy.zone").check()
|
assert codir.join("dummy.zone").check()
|
||||||
assert codir2.join("dummy.zone").check()
|
|
||||||
|
|
||||||
|
def test_template_config(git_dir):
|
||||||
|
template = r"""{
|
||||||
|
"header": "# Managed by dzonegit on $datetime, do not edit.\n",
|
||||||
|
"footer": "# This is the end",
|
||||||
|
"item": " - zone: \"$zonename\"\n file: \"$zonefile\"\n $zonevar\n",
|
||||||
|
"defaultvar": "template: default",
|
||||||
|
"zonevars": {
|
||||||
|
"example.com": "template: signed"
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
output = dzonegit.template_config(str(git_dir), template)
|
||||||
|
assert output.startswith("# Managed by dzonegit")
|
||||||
|
assert " - zone: \"dummy\"\n file: \"" in output
|
||||||
|
assert output.endswith("# This is the end")
|
||||||
|
Reference in New Issue
Block a user