Fix domain template. Drop PDNS 3.x support

This commit is contained in:
Khanh Ngo 2019-12-16 14:23:17 +07:00
parent a891ed38e2
commit 3196297f57
No known key found for this signature in database
GPG key ID: D5FAA6A16150E49E
4 changed files with 49 additions and 147 deletions

View file

@ -3,7 +3,6 @@ import traceback
from flask import current_app from flask import current_app
from urllib.parse import urljoin from urllib.parse import urljoin
from distutils.util import strtobool from distutils.util import strtobool
from distutils.version import StrictVersion
from ..lib import utils from ..lib import utils
from .base import db, domain_apikey from .base import db, domain_apikey
@ -57,11 +56,6 @@ class Domain(db.Model):
self.PDNS_VERSION = Setting().get('pdns_version') self.PDNS_VERSION = Setting().get('pdns_version')
self.API_EXTENDED_URL = utils.pdns_api_extended_uri(self.PDNS_VERSION) self.API_EXTENDED_URL = utils.pdns_api_extended_uri(self.PDNS_VERSION)
if StrictVersion(self.PDNS_VERSION) >= StrictVersion('4.0.0'):
self.NEW_SCHEMA = True
else:
self.NEW_SCHEMA = False
def __repr__(self): def __repr__(self):
return '<Domain {0}>'.format(self.name) return '<Domain {0}>'.format(self.name)
@ -214,9 +208,8 @@ class Domain(db.Model):
headers = {} headers = {}
headers['X-API-Key'] = self.PDNS_API_KEY headers['X-API-Key'] = self.PDNS_API_KEY
if self.NEW_SCHEMA: domain_name = domain_name + '.'
domain_name = domain_name + '.' domain_ns = [ns + '.' for ns in domain_ns]
domain_ns = [ns + '.' for ns in domain_ns]
if soa_edit_api not in ["DEFAULT", "INCREASE", "EPOCH", "OFF"]: if soa_edit_api not in ["DEFAULT", "INCREASE", "EPOCH", "OFF"]:
soa_edit_api = 'DEFAULT' soa_edit_api = 'DEFAULT'

View file

@ -3,7 +3,6 @@ import traceback
import dns.reversename import dns.reversename
import dns.inet import dns.inet
import dns.name import dns.name
from distutils.version import StrictVersion
from flask import current_app from flask import current_app
from urllib.parse import urljoin from urllib.parse import urljoin
from distutils.util import strtobool from distutils.util import strtobool
@ -41,55 +40,6 @@ class Record(object):
self.API_EXTENDED_URL = utils.pdns_api_extended_uri(self.PDNS_VERSION) self.API_EXTENDED_URL = utils.pdns_api_extended_uri(self.PDNS_VERSION)
self.PRETTY_IPV6_PTR = Setting().get('pretty_ipv6_ptr') self.PRETTY_IPV6_PTR = Setting().get('pretty_ipv6_ptr')
if StrictVersion(self.PDNS_VERSION) >= StrictVersion('4.0.0'):
self.NEW_SCHEMA = True
else:
self.NEW_SCHEMA = False
def get_record_data(self, domain):
"""
Query domain's DNS records via API
"""
headers = {}
headers['X-API-Key'] = self.PDNS_API_KEY
try:
jdata = utils.fetch_json(urljoin(
self.PDNS_STATS_URL, self.API_EXTENDED_URL +
'/servers/localhost/zones/{0}'.format(domain)),
timeout=int(
Setting().get('pdns_api_timeout')),
headers=headers)
except Exception as e:
current_app.logger.error(
"Cannot fetch domain's record data from remote powerdns api. DETAIL: {0}"
.format(e))
return False
if self.NEW_SCHEMA:
rrsets = jdata['rrsets']
for rrset in rrsets:
if rrset['records']:
r_name = rrset['name'].rstrip('.')
if self.PRETTY_IPV6_PTR: # only if activated
if rrset['type'] == 'PTR': # only ptr
if 'ip6.arpa' in r_name: # only if v6-ptr
r_name = dns.reversename.to_address(
dns.name.from_text(r_name))
rrset['name'] = r_name
rrset['content'] = rrset['records'][0]['content']
rrset['disabled'] = rrset['records'][0]['disabled']
# Get the record's comment. PDNS support multiple comments
# per record. However, we are only interested in the 1st
# one, for now.
rrset['comment_data'] = {"content": "", "account": ""}
if rrset['comments']:
rrset['comment_data'] = rrset['comments'][0]
return {'records': rrsets}
return jdata
def get_rrsets(self, domain): def get_rrsets(self, domain):
""" """
Query domain's rrsets via PDNS API Query domain's rrsets via PDNS API
@ -524,17 +474,13 @@ class Record(object):
""" """
Check if record is present within domain records, and if it's present set self to found record Check if record is present within domain records, and if it's present set self to found record
""" """
jdata = self.get_record_data(domain) rrsets = self.get_rrsets(domain)
jrecords = jdata['records'] for r in rrsets:
if r['name'].rstrip('.') == self.name and r['type'] == self.type and r['records']:
for jr in jrecords: self.type = r['type']
if jr['name'] == self.name and jr['type'] == self.type: self.status = r['records'][0]['disabled']
self.name = jr['name'] self.ttl = r['ttl']
self.type = jr['type'] self.data = r['records'][0]['content']
self.status = jr['disabled']
self.ttl = jr['ttl']
self.data = jr['content']
self.priority = 10
return True return True
return False return False
@ -545,42 +491,23 @@ class Record(object):
headers = {} headers = {}
headers['X-API-Key'] = self.PDNS_API_KEY headers['X-API-Key'] = self.PDNS_API_KEY
if self.NEW_SCHEMA: data = {
data = { "rrsets": [{
"rrsets": [{ "name":
"name": self.name + '.',
self.name + '.', "type":
"type": self.type,
self.type, "ttl":
"ttl": self.ttl,
self.ttl, "changetype":
"changetype": "REPLACE",
"REPLACE", "records": [{
"records": [{ "content": content,
"content": content, "disabled": self.status,
"disabled": self.status,
}]
}] }]
} }]
else: }
data = {
"rrsets": [{
"name":
self.name,
"type":
self.type,
"changetype":
"REPLACE",
"records": [{
"content": content,
"disabled": self.status,
"name": self.name,
"ttl": self.ttl,
"type": self.type,
"priority": 10
}]
}]
}
try: try:
utils.fetch_json(urljoin( utils.fetch_json(urljoin(
self.PDNS_STATS_URL, self.API_EXTENDED_URL + self.PDNS_STATS_URL, self.API_EXTENDED_URL +

View file

@ -2,7 +2,6 @@ import re
import json import json
import traceback import traceback
from ast import literal_eval from ast import literal_eval
from distutils.version import StrictVersion
from flask import Blueprint, render_template, make_response, url_for, current_app, request, redirect, jsonify, abort, flash from flask import Blueprint, render_template, make_response, url_for, current_app, request, redirect, jsonify, abort, flash
from flask_login import login_required, current_user from flask_login import login_required, current_user
@ -829,59 +828,42 @@ def create_template_from_zone():
created_by=current_user.username) created_by=current_user.username)
history.add() history.add()
# After creating the domain in Domain Template in the,
# local DB. We add records into it Record Template.
records = [] records = []
r = Record()
domain = Domain.query.filter(Domain.name == domain_name).first() domain = Domain.query.filter(Domain.name == domain_name).first()
if domain: if domain:
# query domain info from PowerDNS API # Query zone's rrsets from PowerDNS API
zone_info = r.get_record_data(domain.name) rrsets = Record().get_rrsets(domain.name)
if zone_info: if rrsets:
jrecords = zone_info['records'] for r in rrsets:
name = '@' if r['name'] == domain_name + '.' else r[
if StrictVersion(Setting().get( 'name'].replace('.{}.'.format(domain_name), '')
'pdns_version')) >= StrictVersion('4.0.0'): for record in r['records']:
for jr in jrecords: t_record = DomainTemplateRecord(
if jr['type'] in Setting().get_records_allow_to_edit():
name = '@' if jr['name'] == domain_name else re.sub(
r'\.{}$'.format(domain_name), '', jr['name'])
for subrecord in jr['records']:
record = DomainTemplateRecord(
name=name,
type=jr['type'],
status=True
if subrecord['disabled'] else False,
ttl=jr['ttl'],
data=subrecord['content'],
comment=jr['comment_data']['content'])
records.append(record)
else:
for jr in jrecords:
if jr['type'] in Setting().get_records_allow_to_edit():
name = '@' if jr['name'] == domain_name else re.sub(
r'\.{}$'.format(domain_name), '', jr['name'])
record = DomainTemplateRecord(
name=name, name=name,
type=jr['type'], type=r['type'],
status=True if jr['disabled'] else False, status=False if record['disabled'] else True,
ttl=jr['ttl'], ttl=r['ttl'],
data=jr['content'], data=record['content'])
comment=jr['comment_data']['content']) records.append(t_record)
records.append(record)
result_records = t.replace_records(records) result = t.replace_records(records)
if result_records['status'] == 'ok': if result['status'] == 'ok':
return make_response( return make_response(
jsonify({ jsonify({
'status': 'ok', 'status': 'ok',
'msg': result['msg'] 'msg': result['msg']
}), 200) }), 200)
else: else:
# Revert the domain template (remove it)
# ff we cannot add records.
t.delete_template() t.delete_template()
return make_response( return make_response(
jsonify({ jsonify({
'status': 'error', 'status': 'error',
'msg': result_records['msg'] 'msg': result['msg']
}), 500) }), 500)
else: else:
@ -918,7 +900,7 @@ def edit_template(template):
record = DomainTemplateRecord( record = DomainTemplateRecord(
name=jr.name, name=jr.name,
type=jr.type, type=jr.type,
status='Disabled' if jr.status else 'Active', status='Active' if jr.status else 'Disabled',
ttl=jr.ttl, ttl=jr.ttl,
data=jr.data, data=jr.data,
comment=jr.comment if jr.comment else '') comment=jr.comment if jr.comment else '')
@ -952,14 +934,14 @@ def apply_records(template):
type = j['record_type'] type = j['record_type']
data = j['record_data'] data = j['record_data']
comment = j['record_comment'] comment = j['record_comment']
disabled = True if j['record_status'] == 'Disabled' else False status = 0 if j['record_status'] == 'Disabled' else 1
ttl = int(j['record_ttl']) if j['record_ttl'] else 3600 ttl = int(j['record_ttl']) if j['record_ttl'] else 3600
dtr = DomainTemplateRecord(name=name, dtr = DomainTemplateRecord(name=name,
type=type, type=type,
data=data, data=data,
comment=comment, comment=comment,
status=disabled, status=status,
ttl=ttl) ttl=ttl)
records.append(dtr) records.append(dtr)

View file

@ -168,7 +168,7 @@ def add():
record_row = { record_row = {
'record_data': template_record.data, 'record_data': template_record.data,
'record_name': template_record.name, 'record_name': template_record.name,
'record_status': template_record.status, 'record_status': 'Active' if template_record.status else 'Disabled',
'record_ttl': template_record.ttl, 'record_ttl': template_record.ttl,
'record_type': template_record.type, 'record_type': template_record.type,
'comment_data': [{'content': template_record.comment, 'account': ''}] 'comment_data': [{'content': template_record.comment, 'account': ''}]