Add MX and tests

This commit is contained in:
Fergal Moran
2020-11-18 20:48:34 +00:00
parent 3c08c8fa61
commit 9a3bcad07d
7 changed files with 73 additions and 140 deletions

View File

@@ -1,2 +1,2 @@
from .dns import DnsZone, DnsNameServer, DnsHost from .dns import DnsZone, DnsNameServer, DnsMailExchanger, DnsHost
from .user import User from .user import User

View File

@@ -10,30 +10,6 @@ from app import db
from app.models._basemodel import _BaseModelMixin from app.models._basemodel import _BaseModelMixin
@dataclass
class DnsNameServer(db.Model, _BaseModelMixin, FlaskSerializeMixin):
__tablename__ = 'dns_nameservers'
host = db.Column(db.String(255), unique=True, nullable=False)
ip = db.Column(IPAddressType(255), nullable=False)
ttl = db.Column(db.Integer(), nullable=False, default=30)
zone_id = db.Column(db.Integer, db.ForeignKey('dns_zones.id'))
zone = relationship("DnsZone", back_populates="nameservers")
def __init__(self, zone, host, ip, ttl=30):
self.zone = zone
self.host = host
self.ip = ip
self.ttl = ttl
def to_dict(self):
return {
'name': self.host,
'ip': self.ip,
'ttl': self.ttl
}
@dataclass @dataclass
class DnsZone(db.Model, _BaseModelMixin, FlaskSerializeMixin): class DnsZone(db.Model, _BaseModelMixin, FlaskSerializeMixin):
__tablename__ = 'dns_zones' __tablename__ = 'dns_zones'
@@ -64,6 +40,7 @@ class DnsZone(db.Model, _BaseModelMixin, FlaskSerializeMixin):
'serial': self.serial, 'serial': self.serial,
'admin': self.admin, 'admin': self.admin,
'nameservers': [ns.to_dict() for ns in self.nameservers], 'nameservers': [ns.to_dict() for ns in self.nameservers],
'mailexchangers': [mx.to_dict() for mx in self.mailexchangers],
'hosts': [host.to_dict() for host in self.hosts] 'hosts': [host.to_dict() for host in self.hosts]
} }
return ret_data return ret_data
@@ -77,6 +54,60 @@ class DnsZone(db.Model, _BaseModelMixin, FlaskSerializeMixin):
hosts = relationship("DnsHost", back_populates="zone") hosts = relationship("DnsHost", back_populates="zone")
nameservers = relationship("DnsNameServer", back_populates="zone") nameservers = relationship("DnsNameServer", back_populates="zone")
mailexchangers = relationship("DnsMailExchanger", back_populates="zone")
@dataclass
class DnsNameServer(db.Model, _BaseModelMixin, FlaskSerializeMixin):
__tablename__ = 'dns_nameservers'
host = db.Column(db.String(255), unique=True, nullable=False)
ip = db.Column(IPAddressType(255), nullable=False)
ttl = db.Column(db.Integer(), nullable=False, default=30)
zone_id = db.Column(db.Integer, db.ForeignKey('dns_zones.id'))
zone = relationship("DnsZone", back_populates="nameservers")
def __init__(self, zone, host, ip, ttl=30):
self.zone = zone
self.host = host
self.ip = ip
self.ttl = ttl
def to_dict(self):
return {
'name': self.host,
'ip': self.ip,
'ttl': self.ttl
}
@dataclass
class DnsMailExchanger(db.Model, _BaseModelMixin, FlaskSerializeMixin):
__tablename__ = 'dns_mailexchangers'
id = db.Column(db.Integer, primary_key=True)
zone_id = db.Column(db.Integer, db.ForeignKey('dns_zones.id'))
zone = relationship("DnsZone", back_populates="mailexchangers")
host = db.Column(db.String(255), unique=True, nullable=False)
preference = db.Column(db.Integer, nullable=False)
ttl = db.Column(db.Integer(), nullable=False)
def __init__(self, zone, host, preference, ttl=30):
self.zone = zone
self.host = host
self.ttl = ttl
self.preference = preference
pass
def to_dict(self):
return {
'id': self.id,
'name': self.host,
'preference': self.preference,
'ttl': self.ttl,
'created_on': self.created_on,
}
@dataclass @dataclass

View File

@@ -1,4 +1,4 @@
from app.models import DnsZone, User, DnsHost, DnsNameServer from app.models import DnsZone, User, DnsHost, DnsNameServer, DnsMailExchanger
class DbSeeder(object): class DbSeeder(object):
@@ -28,16 +28,16 @@ class DbSeeder(object):
) )
self._db.session.add(ns) self._db.session.add(ns)
def _create_hosts(self, zone): def _create_mailexchangers(self, zone):
for i in range(1, 11): for i in range(1, 11):
host = DnsHost( host = DnsMailExchanger(
zone, zone,
'host-{}'.format(i), 'mail-{}.bitchmints.com'.format(i),
'10.1.1.{}'.format(i) i
) )
self._db.session.add(host) self._db.session.add(host)
def _create_mx_records(self, zone): def _create_hosts(self, zone):
for i in range(1, 11): for i in range(1, 11):
host = DnsHost( host = DnsHost(
zone, zone,
@@ -53,6 +53,7 @@ class DbSeeder(object):
self._create_user() self._create_user()
z = self._create_zone() z = self._create_zone()
self._create_nameservers(z) self._create_nameservers(z)
self._create_mailexchangers(z)
self._create_hosts(z) self._create_hosts(z)
self._db.session.commit() self._db.session.commit()

View File

@@ -1,6 +1,6 @@
import uuid import uuid
from app.models import User, DnsZone, DnsNameServer, DnsHost from app.models import User, DnsZone, DnsNameServer, DnsHost, DnsMailExchanger
class TestDatabaseUpdate: class TestDatabaseUpdate:
@@ -8,6 +8,7 @@ class TestDatabaseUpdate:
assert db.session.query(User).count() == 1 assert db.session.query(User).count() == 1
assert db.session.query(DnsZone).count() == 1 assert db.session.query(DnsZone).count() == 1
assert db.session.query(DnsNameServer).count() == 2 assert db.session.query(DnsNameServer).count() == 2
assert db.session.query(DnsMailExchanger).count() == 10
assert db.session.query(DnsHost).count() == 10 assert db.session.query(DnsHost).count() == 10
def test_serial_on_create(self, db) -> None: def test_serial_on_create(self, db) -> None:

View File

@@ -11,7 +11,11 @@ class TestUserRoutes:
assert len(zones) == 1 assert len(zones) == 1
assert zones[0]['name'] == 'bitchmints.com' assert zones[0]['name'] == 'bitchmints.com'
assert len(zones[0]['nameservers']) == 2 assert len(zones[0]['nameservers']) == 2
assert zones[0]['nameservers'][0]['name'] == 'host-1.bitchmints.com'
assert zones[0]['nameservers'][1]['name'] == 'host-2.bitchmints.com' for i in range(0, 2):
assert zones[0]['nameservers'][0]['ip'] == '10.1.1.101' assert zones[0]['nameservers'][i]['ip'] == '10.1.1.10{}'.format(i + 1)
assert zones[0]['nameservers'][1]['ip'] == '10.1.1.102' assert zones[0]['nameservers'][i]['name'] == 'host-{}.bitchmints.com'.format(i + 1)
for i in range(0, 10):
assert zones[0]['mailexchangers'][i]['name'] == 'mail-{}.bitchmints.com'.format(i + 1)
assert zones[0]['mailexchangers'][i]['preference'] == i + 1

View File

@@ -1,30 +0,0 @@
"""Add TTL to nameserver.
Revision ID: 4fa78fdd3f74
Revises: b780f60b3019
Create Date: 2020-11-18 16:55:35.514517
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
# revision identifiers, used by Alembic.
revision = '4fa78fdd3f74'
down_revision = 'b780f60b3019'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('dns_nameservers', sa.Column('ttl', sa.Integer(), nullable=True))
op.execute('UPDATE dns_nameservers SET ttl = 30')
op.alter_column('dns_nameservers', 'ttl', nullable=False)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('dns_nameservers', 'ttl')
# ### end Alembic commands ###

View File

@@ -1,74 +0,0 @@
"""Initial migration.
Revision ID: b780f60b3019
Revises:
Create Date: 2020-11-16 13:00:43.391154
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
# revision identifiers, used by Alembic.
revision = 'b780f60b3019'
down_revision = None
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('dns_zones',
sa.Column('created_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('updated_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('zone_name', sa.String(length=253), nullable=False),
sa.Column('serial', sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('zone_name')
)
op.create_table('users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('updated_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('email', sa.String(length=120), nullable=False),
sa.Column('full_name', sa.String(length=120), nullable=True),
sa.Column('password', sa.String(length=255), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
)
op.create_table('dns_hosts',
sa.Column('created_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('updated_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('zone_id', sa.Integer(), nullable=True),
sa.Column('host', sa.String(length=255), nullable=False),
sa.Column('ip', sqlalchemy_utils.types.ip_address.IPAddressType(length=255), nullable=False),
sa.Column('type', sa.String(length=10), nullable=False),
sa.Column('ttl', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['zone_id'], ['dns_zones.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('host')
)
op.create_table('dns_nameservers',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('updated_on', sa.DateTime(), server_default=sa.text('now()'), nullable=True),
sa.Column('host', sa.String(length=255), nullable=False),
sa.Column('ip', sqlalchemy_utils.types.ip_address.IPAddressType(length=255), nullable=False),
sa.Column('zone_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['zone_id'], ['dns_zones.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('host')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('dns_nameservers')
op.drop_table('dns_hosts')
op.drop_table('users')
op.drop_table('dns_zones')
# ### end Alembic commands ###