Improve DNS table models
This commit adds Meta information and __str__ methods to all DNS table models. The new methods are now covered with new tests. The new constants DNS_DOMAIN_METADATA_KINDS and DNS_TSIG_KEY_ALGORITHMS are defined and used in the DNSDomainMetadata and DNSTSIGKey models. A matching database schema migration is added. Addresses #17
This commit is contained in:
parent
1df2534cf3
commit
c058cc7b1d
3 changed files with 193 additions and 7 deletions
44
gnuviechadmin/domains/migrations/0004_auto_20151107_1708.py
Normal file
44
gnuviechadmin/domains/migrations/0004_auto_20151107_1708.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('domains', '0003_auto_20151105_2133'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='dnscomment',
|
||||||
|
options={'verbose_name': 'DNS comment', 'verbose_name_plural': 'DNS comments'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='dnscryptokey',
|
||||||
|
options={'verbose_name': 'DNS crypto key', 'verbose_name_plural': 'DNS crypto keys'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='dnsdomainmetadata',
|
||||||
|
options={'verbose_name': 'DNS domain metadata item', 'verbose_name_plural': 'DNS domain metadata items'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='dnssupermaster',
|
||||||
|
options={'verbose_name': 'DNS supermaster', 'verbose_name_plural': 'DNS supermasters'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='dnstsigkey',
|
||||||
|
options={'verbose_name': 'DNS TSIG key', 'verbose_name_plural': 'DNS TSIG keys'},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='dnsdomainmetadata',
|
||||||
|
name='kind',
|
||||||
|
field=models.CharField(max_length=32, choices=[('ALLOW-DNSUPDATE-FROM', 'ALLOW-DNSUPDATE-FROM'), ('ALSO-NOTIFY', 'ALSO-NOTIFY'), ('AXFR-MASTER-TSIG', 'AXFR-MASTER-TSIG'), ('AXFR-SOURCE', 'AXFR-SOURCE'), ('FORWARD-DNSUPDATE', 'FORWARD-DNSUPDATE'), ('GSS-ACCEPTOR-PRINCIPAL', 'GSS-ACCEPTOR-PRINCIPAL'), ('GSS-ALLOW-AXFR-PRINCIPAL', 'GSS-ALLOW-AXFR-PRINCIPAL'), ('LUA-AXFR-SCRIPT', 'LUA-AXFR-SCRIPT'), ('NSEC3NARROW', 'NSEC3NARROW'), ('NSEC3PARAM', 'NSEC3PARAM'), ('PRESIGNED', 'PRESIGNED'), ('PUBLISH_CDNSKEY', 'PUBLISH_CDNSKEY'), ('PUBLISH_CDS', 'PUBLISH_CDS'), ('SOA-EDIT', 'SOA-EDIT'), ('SOA-EDIT-DNSUPDATE', 'SOA-EDIT-DNSUPDATE'), ('TSIG-ALLOW-AXFR', 'TSIG-ALLOW-AXFR'), ('TSIG-ALLOW-DNSUPDATE', 'TSIG-ALLOW-DNSUPDATE')]),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='dnstsigkey',
|
||||||
|
name='algorithm',
|
||||||
|
field=models.CharField(max_length=50, choices=[('hmac-md5', 'HMAC MD5'), ('hmac-sha1', 'HMAC SHA1'), ('hmac-sha224', 'HMAC SHA224'), ('hmac-sha256', 'HMAC SHA256'), ('hmac-sha384', 'HMAC SHA384'), ('hmac-sha512', 'HMAC SHA512')]),
|
||||||
|
),
|
||||||
|
]
|
|
@ -19,6 +19,36 @@ DNS_DOMAIN_TYPES = Choices(
|
||||||
('NATIVE', _('Native')),
|
('NATIVE', _('Native')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# see https://doc.powerdns.com/md/authoritative/domainmetadata/
|
||||||
|
DNS_DOMAIN_METADATA_KINDS = Choices(
|
||||||
|
'ALLOW-DNSUPDATE-FROM',
|
||||||
|
'ALSO-NOTIFY',
|
||||||
|
'AXFR-MASTER-TSIG',
|
||||||
|
'AXFR-SOURCE',
|
||||||
|
'FORWARD-DNSUPDATE',
|
||||||
|
'GSS-ACCEPTOR-PRINCIPAL',
|
||||||
|
'GSS-ALLOW-AXFR-PRINCIPAL',
|
||||||
|
'LUA-AXFR-SCRIPT',
|
||||||
|
'NSEC3NARROW',
|
||||||
|
'NSEC3PARAM',
|
||||||
|
'PRESIGNED',
|
||||||
|
'PUBLISH_CDNSKEY',
|
||||||
|
'PUBLISH_CDS',
|
||||||
|
'SOA-EDIT',
|
||||||
|
'SOA-EDIT-DNSUPDATE',
|
||||||
|
'TSIG-ALLOW-AXFR',
|
||||||
|
'TSIG-ALLOW-DNSUPDATE',
|
||||||
|
)
|
||||||
|
|
||||||
|
DNS_TSIG_KEY_ALGORITHMS = Choices(
|
||||||
|
('hmac-md5', _('HMAC MD5')),
|
||||||
|
('hmac-sha1', _('HMAC SHA1')),
|
||||||
|
('hmac-sha224', _('HMAC SHA224')),
|
||||||
|
('hmac-sha256', _('HMAC SHA256')),
|
||||||
|
('hmac-sha384', _('HMAC SHA384')),
|
||||||
|
('hmac-sha512', _('HMAC SHA512')),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class DomainBase(TimeStampedModel):
|
class DomainBase(TimeStampedModel):
|
||||||
|
@ -144,6 +174,7 @@ class DNSDomain(DomainBase):
|
||||||
return self.domain
|
return self.domain
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class DNSRecord(models.Model):
|
class DNSRecord(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represents a DNS record. The model is similar to the record
|
This model represents a DNS record. The model is similar to the record
|
||||||
|
@ -195,7 +226,12 @@ class DNSRecord(models.Model):
|
||||||
['name', 'recordtype']
|
['name', 'recordtype']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{name} IN {type} {content}".format(
|
||||||
|
name=self.name, type=self.recordtype, content=self.content)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class DNSSupermaster(models.Model):
|
class DNSSupermaster(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represents the supermasters table in the PowerDNS schema
|
This model represents the supermasters table in the PowerDNS schema
|
||||||
|
@ -217,15 +253,24 @@ class DNSSupermaster(models.Model):
|
||||||
settings.AUTH_USER_MODEL, verbose_name=_('customer'))
|
settings.AUTH_USER_MODEL, verbose_name=_('customer'))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
verbose_name = _('DNS supermaster')
|
||||||
|
verbose_name_plural = _('DNS supermasters')
|
||||||
unique_together = (
|
unique_together = (
|
||||||
('ip', 'nameserver')
|
('ip', 'nameserver')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{ip} {nameserver}".format(
|
||||||
|
ip=self.ip, nameserver=self.nameserver)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class DNSComment(models.Model):
|
class DNSComment(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represents the comments table in the PowerDNS schema specified
|
This model represents the comments table in the PowerDNS schema specified
|
||||||
in https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/.
|
in https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/. The
|
||||||
|
comments table is used to store user comments related to individual DNS
|
||||||
|
records.
|
||||||
|
|
||||||
CREATE TABLE comments (
|
CREATE TABLE comments (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
@ -257,17 +302,26 @@ class DNSComment(models.Model):
|
||||||
# check constraint is added via RunSQL in migration
|
# check constraint is added via RunSQL in migration
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
verbose_name = _('DNS comment')
|
||||||
|
verbose_name_plural = _('DNS comments')
|
||||||
index_together = [
|
index_together = [
|
||||||
['name', 'commenttype'],
|
['name', 'commenttype'],
|
||||||
['domain', 'modified_at']
|
['domain', 'modified_at']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{name} IN {type}: {comment}".format(
|
||||||
|
name=self.name, type=self.commenttype, comment=self.comment)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class DNSDomainMetadata(models.Model):
|
class DNSDomainMetadata(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represents the domainmetadata table in the PowerDNS schema
|
This model represents the domainmetadata table in the PowerDNS schema
|
||||||
specified in
|
specified in
|
||||||
https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/.
|
https://doc.powerdns.com/md/authoritative/backend-generic-mypgsql/.
|
||||||
|
The domainmetadata table is used to store domain meta data as described in
|
||||||
|
https://doc.powerdns.com/md/authoritative/domainmetadata/.
|
||||||
|
|
||||||
CREATE TABLE domainmetadata (
|
CREATE TABLE domainmetadata (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
|
@ -279,10 +333,19 @@ class DNSDomainMetadata(models.Model):
|
||||||
CREATE INDEX domainidmetaindex ON domainmetadata(domain_id);
|
CREATE INDEX domainidmetaindex ON domainmetadata(domain_id);
|
||||||
"""
|
"""
|
||||||
domain = models.ForeignKey('DNSDomain')
|
domain = models.ForeignKey('DNSDomain')
|
||||||
kind = models.CharField(max_length=32)
|
kind = models.CharField(max_length=32, choices=DNS_DOMAIN_METADATA_KINDS)
|
||||||
content = models.TextField()
|
content = models.TextField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('DNS domain metadata item')
|
||||||
|
verbose_name_plural = _('DNS domain metadata items')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{domain} {kind} {content}".format(
|
||||||
|
domain=self.domain.domain, kind=self.kind, content=self.content)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class DNSCryptoKey(models.Model):
|
class DNSCryptoKey(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represents the cryptokeys table in the PowerDNS schema
|
This model represents the cryptokeys table in the PowerDNS schema
|
||||||
|
@ -304,7 +367,16 @@ class DNSCryptoKey(models.Model):
|
||||||
active = models.BooleanField(default=True)
|
active = models.BooleanField(default=True)
|
||||||
content = models.TextField()
|
content = models.TextField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('DNS crypto key')
|
||||||
|
verbose_name_plural = _('DNS crypto keys')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{domain} {content}".format(
|
||||||
|
domain=self.domain.domain, content=self.content)
|
||||||
|
|
||||||
|
|
||||||
|
@python_2_unicode_compatible
|
||||||
class DNSTSIGKey(models.Model):
|
class DNSTSIGKey(models.Model):
|
||||||
"""
|
"""
|
||||||
This model represents the tsigkeys table in the PowerDNS schema specified
|
This model represents the tsigkeys table in the PowerDNS schema specified
|
||||||
|
@ -321,11 +393,17 @@ class DNSTSIGKey(models.Model):
|
||||||
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
|
CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);
|
||||||
"""
|
"""
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
algorithm = models.CharField(max_length=50)
|
algorithm = models.CharField(max_length=50, choices=DNS_TSIG_KEY_ALGORITHMS)
|
||||||
secret = models.CharField(max_length=255)
|
secret = models.CharField(max_length=255)
|
||||||
# check constraint is added via RunSQL in migration
|
# check constraint is added via RunSQL in migration
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
verbose_name = _('DNS TSIG key')
|
||||||
|
verbose_name_plural = _('DNS TSIG keys')
|
||||||
unique_together = [
|
unique_together = [
|
||||||
['name', 'algorithm']
|
['name', 'algorithm']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "{name} {algorithm} XXXX".format(
|
||||||
|
name=self.name, algorithm=self.algorithm)
|
||||||
|
|
|
@ -10,9 +10,16 @@ from django.test import TestCase
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from domains.models import (
|
from domains.models import (
|
||||||
|
DNSComment,
|
||||||
|
DNSCryptoKey,
|
||||||
|
DNSDomain,
|
||||||
|
DNSDomainMetadata,
|
||||||
|
DNSRecord,
|
||||||
|
DNSSupermaster,
|
||||||
|
DNSTSIGKey,
|
||||||
DomainBase,
|
DomainBase,
|
||||||
MailDomain,
|
|
||||||
HostingDomain,
|
HostingDomain,
|
||||||
|
MailDomain,
|
||||||
)
|
)
|
||||||
from hostingpackages.models import (
|
from hostingpackages.models import (
|
||||||
CustomerHostingPackage,
|
CustomerHostingPackage,
|
||||||
|
@ -27,14 +34,14 @@ TEST_USER = 'test'
|
||||||
|
|
||||||
class DomainBaseTest(TestCase):
|
class DomainBaseTest(TestCase):
|
||||||
|
|
||||||
def test__str__(self):
|
def test___str__(self):
|
||||||
db = DomainBase(domain='test')
|
db = DomainBase(domain='test')
|
||||||
self.assertEqual(str(db), 'test')
|
self.assertEqual(str(db), 'test')
|
||||||
|
|
||||||
|
|
||||||
class MailDomainTest(TestCase):
|
class MailDomainTest(TestCase):
|
||||||
|
|
||||||
def test__str__(self):
|
def test___str__(self):
|
||||||
md = MailDomain.objects.create(domain='example.org')
|
md = MailDomain.objects.create(domain='example.org')
|
||||||
self.assertEqual(str(md), 'example.org')
|
self.assertEqual(str(md), 'example.org')
|
||||||
|
|
||||||
|
@ -77,8 +84,65 @@ class HostingDomainManagerTest(TestCase):
|
||||||
self.assertIsNotNone(hostingdomain)
|
self.assertIsNotNone(hostingdomain)
|
||||||
self.assertTrue(hostingdomain.customer, package.customer)
|
self.assertTrue(hostingdomain.customer, package.customer)
|
||||||
|
|
||||||
|
|
||||||
class HostingDomainTest(TestCase):
|
class HostingDomainTest(TestCase):
|
||||||
|
|
||||||
def test__str__(self):
|
def test___str__(self):
|
||||||
hostingdomain = HostingDomain(domain='test')
|
hostingdomain = HostingDomain(domain='test')
|
||||||
self.assertEqual(str(hostingdomain), 'test')
|
self.assertEqual(str(hostingdomain), 'test')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSDomainTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnsdomain = DNSDomain(domain='test')
|
||||||
|
self.assertEqual(str(dnsdomain), 'test')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSRecordTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnsrecord = DNSRecord(
|
||||||
|
name='localhost', recordtype='A', content='127.0.0.1')
|
||||||
|
self.assertEqual(str(dnsrecord), 'localhost IN A 127.0.0.1')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSSupermasterTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnssupermaster = DNSSupermaster(
|
||||||
|
ip='127.0.0.1', nameserver='dns.example.org')
|
||||||
|
self.assertEqual(str(dnssupermaster), '127.0.0.1 dns.example.org')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSCommentTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnscomment = DNSComment(
|
||||||
|
name='localhost', commenttype='A', comment='good stuff')
|
||||||
|
self.assertEqual(str(dnscomment), 'localhost IN A: good stuff')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSDomainMetadataTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnsdomain = DNSDomain(domain='test')
|
||||||
|
dnsdomainmetadata = DNSDomainMetadata(
|
||||||
|
domain=dnsdomain, kind='SOA-EDIT', content='INCEPTION')
|
||||||
|
self.assertEqual(str(dnsdomainmetadata), 'test SOA-EDIT INCEPTION')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSCryptoKeyTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnsdomain = DNSDomain(domain='test')
|
||||||
|
dnscryptokey = DNSCryptoKey(domain=dnsdomain, content='testvalue')
|
||||||
|
self.assertEqual(str(dnscryptokey), 'test testvalue')
|
||||||
|
|
||||||
|
|
||||||
|
class DNSTSIGKeyTest(TestCase):
|
||||||
|
|
||||||
|
def test___str__(self):
|
||||||
|
dnstsigkey = DNSTSIGKey(
|
||||||
|
name='testkey', algorithm='hmac-md5', secret='dummykey')
|
||||||
|
self.assertEqual(str(dnstsigkey), 'testkey hmac-md5 XXXX')
|
||||||
|
|
Loading…
Reference in a new issue