Initial start of the context/server model, including test framework.
All checks were successful
pda-new unit tests / Run-unit-tests (push) Successful in 8s
All checks were successful
pda-new unit tests / Run-unit-tests (push) Successful in 8s
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,7 +3,7 @@
|
||||
*.pot
|
||||
*.pyc
|
||||
__pycache__
|
||||
db.sqlite3
|
||||
*.sqlite3
|
||||
media
|
||||
staticfiles/
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ INSTALLED_APPS = [
|
||||
"django.contrib.staticfiles",
|
||||
"allauth",
|
||||
"allauth.account",
|
||||
'pdns',
|
||||
]
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
@@ -50,6 +51,7 @@ MIDDLEWARE = [
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
"allauth.account.middleware.AccountMiddleware",
|
||||
]
|
||||
|
||||
@@ -77,7 +79,7 @@ DEFAULT_DB = {
|
||||
'ENGINE': f"django.db.backends.{DB_ENGINE}",
|
||||
}
|
||||
if DB_ENGINE=='sqlite3':
|
||||
DEFAULT_DB['NAME'] = os.path.join('BASE_DIR',
|
||||
DEFAULT_DB['NAME'] = os.path.join(BASE_DIR,
|
||||
env('DB_NAME', default='pdanext.sqlite3'))
|
||||
else:
|
||||
DEFAULT_DB['NAME'] = env('DB_NAME')
|
||||
@@ -93,6 +95,8 @@ DATABASES = {
|
||||
'default': DEFAULT_DB,
|
||||
}
|
||||
|
||||
print('Database: %s' % DATABASES['default']) if DEBUG else None
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
|
||||
2
src/pdns/__init__.py
Normal file
2
src/pdns/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# __init__.py needs to exist or django won't load the module.
|
||||
|
||||
65
src/pdns/migrations/0001_initial.py
Normal file
65
src/pdns/migrations/0001_initial.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# Generated by Django 5.2.5 on 2025-10-20 04:54
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="PDNSContext",
|
||||
fields=[
|
||||
(
|
||||
"name",
|
||||
models.CharField(
|
||||
max_length=20,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
unique=True,
|
||||
verbose_name="Name",
|
||||
),
|
||||
),
|
||||
(
|
||||
"description",
|
||||
models.TextField(blank=True, null=True, verbose_name="Description"),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="PDNSServer",
|
||||
fields=[
|
||||
(
|
||||
"name",
|
||||
models.CharField(
|
||||
max_length=40,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
unique=True,
|
||||
verbose_name="Name",
|
||||
),
|
||||
),
|
||||
(
|
||||
"server_uri",
|
||||
models.URLField(
|
||||
help_text="Prefer IP addresses; use FQDN at your own risk.",
|
||||
max_length=80,
|
||||
verbose_name="Server URL",
|
||||
),
|
||||
),
|
||||
(
|
||||
"fk_network",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="servers",
|
||||
to="pdns.pdnscontext",
|
||||
verbose_name="Context",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,34 @@
|
||||
# Generated by Django 5.2.5 on 2025-10-20 07:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pdns", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="pdnsserver",
|
||||
name="alive",
|
||||
field=models.BooleanField(
|
||||
default=False, editable=False, verbose_name="Alive status"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="pdnsserver",
|
||||
name="last_checked",
|
||||
field=models.DateTimeField(
|
||||
editable=False, null=True, verbose_name="Last checked"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="pdnsserver",
|
||||
name="last_seen",
|
||||
field=models.DateTimeField(
|
||||
editable=False, null=True, verbose_name="Last seen online"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 5.2.5 on 2025-10-20 08:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pdns", "0002_pdnsserver_alive_pdnsserver_last_checked_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="pdnsserver",
|
||||
old_name="fk_network",
|
||||
new_name="context",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="pdnsserver",
|
||||
name="alive",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="pdnsserver",
|
||||
name="online",
|
||||
field=models.BooleanField(
|
||||
default=False, editable=False, verbose_name="Online status"
|
||||
),
|
||||
),
|
||||
]
|
||||
0
src/pdns/migrations/__init__.py
Normal file
0
src/pdns/migrations/__init__.py
Normal file
99
src/pdns/models.py
Normal file
99
src/pdns/models.py
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
#
|
||||
|
||||
from django.db import models
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
# Okay, going to illustrate my thinking here:
|
||||
# A ##Context## is a set of servers that operate together as
|
||||
# authoritative for a group of zones.
|
||||
|
||||
# (I was going to call it a Network, but then I found out
|
||||
# about https://doc.powerdns.com/authoritative/views.html )
|
||||
|
||||
# All ##Servers## within a Context are presumed to be
|
||||
# using the same database and be otherwise interchangeable,
|
||||
# Although given the limitations of some backends they can
|
||||
# be set to read-only.
|
||||
|
||||
class PDNSContext(models.Model):
|
||||
name = models.CharField(verbose_name=_('Name'),
|
||||
max_length=20,
|
||||
unique=True,
|
||||
primary_key=True,
|
||||
)
|
||||
|
||||
description = models.TextField(verbose_name=_('Description'),
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def total_servers(self):
|
||||
return self.servers.all().count()
|
||||
|
||||
def online_servers(self):
|
||||
return self.servers.filter(online=True).count()
|
||||
|
||||
def offline_servers(self):
|
||||
return self.servers.filter(online=False).count()
|
||||
|
||||
def status(self):
|
||||
return _('Context %(name)s: %(total)d total, %(online)d online, %(offline)d offline.') % {
|
||||
'name': self.name,
|
||||
'total': self.total_servers(),
|
||||
'online': self.online_servers(),
|
||||
'offline': self.offline_servers()}
|
||||
|
||||
|
||||
class PDNSServer(models.Model):
|
||||
name = models.CharField(verbose_name=_('Name'),
|
||||
max_length=40,
|
||||
unique=True,
|
||||
primary_key=True,
|
||||
)
|
||||
|
||||
server_uri = models.URLField(verbose_name=_('Server URL'),
|
||||
help_text='Prefer IP addresses; use FQDN at your own risk.',
|
||||
max_length=80,
|
||||
blank=False,
|
||||
null=False
|
||||
)
|
||||
|
||||
context=models.ForeignKey(PDNSContext,
|
||||
verbose_name=_('Context'),
|
||||
on_delete=models.PROTECT,
|
||||
related_name='servers'
|
||||
)
|
||||
|
||||
online = models.BooleanField(verbose_name=_('Online status'),
|
||||
editable=False,
|
||||
default=False
|
||||
)
|
||||
|
||||
last_checked = models.DateTimeField(verbose_name=_('Last checked'),
|
||||
editable=False,
|
||||
null=True
|
||||
)
|
||||
|
||||
last_seen = models.DateTimeField(verbose_name=_('Last seen online'),
|
||||
editable=False,
|
||||
null=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
selfstr= _("%(name)s (%(context)s): %(url)s") % { 'name': self.name,
|
||||
'context': self.context.name,
|
||||
'url': self.server_uri}
|
||||
return selfstr
|
||||
|
||||
def status(self):
|
||||
status = _('Online') if self.online else _('Offline')
|
||||
return _('%(status)s since %(time)s') % {
|
||||
'status': status,
|
||||
'time': self.last_checked
|
||||
}
|
||||
73
src/pdns/test_models.py
Normal file
73
src/pdns/test_models.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
from django.test import TestCase
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext as _
|
||||
from unittest import skip
|
||||
|
||||
from .models import (
|
||||
PDNSContext,
|
||||
PDNSServer
|
||||
)
|
||||
|
||||
# Tests are run in transactions, which means that for every test_*() function
|
||||
# the database restores to what's created during setUp()
|
||||
|
||||
class PDNSModelTestCase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.test_time = now()
|
||||
tc = PDNSContext.objects.create(name='test context')
|
||||
PDNSServer.objects.create(name='test server',
|
||||
server_uri='https://localhost:8081',
|
||||
context=tc,
|
||||
online=True,
|
||||
last_seen=self.test_time,
|
||||
last_checked=self.test_time)
|
||||
self.context_target = 'test context'
|
||||
self.server_target = 'test server (test context): https://localhost:8081'
|
||||
self.server_status_target = _('%(status)s since %(date)s') % {
|
||||
'status': _('Online'),
|
||||
'date': self.test_time
|
||||
}
|
||||
self.server_status_offline_target = _('%(status)s since %(date)s') % {
|
||||
'status': _('Offline'),
|
||||
'date': self.test_time
|
||||
}
|
||||
return True
|
||||
|
||||
def test_server(self):
|
||||
test_server = PDNSServer.objects.get(name='test server')
|
||||
self.assertEqual(test_server.__str__(), self.server_target)
|
||||
self.assertEqual(test_server.status(), self.server_status_target)
|
||||
|
||||
def test_server_offline(self):
|
||||
test_server = PDNSServer.objects.get(name='test server')
|
||||
test_server.online = False
|
||||
self.assertEqual(test_server.status(), self.server_status_offline_target)
|
||||
|
||||
def test_context(self):
|
||||
test_context = PDNSContext.objects.get(name='test context')
|
||||
self.assertEqual(test_context.__str__(), self.context_target)
|
||||
|
||||
def test_context_onoff(self):
|
||||
test_context = PDNSContext.objects.get(name='test context')
|
||||
self.assertEqual(test_context.total_servers(),1)
|
||||
self.assertEqual(test_context.online_servers(),1)
|
||||
self.assertEqual(test_context.offline_servers(),0)
|
||||
|
||||
def test_context_offline(self):
|
||||
test_context = PDNSContext.objects.get(name='test context')
|
||||
test_server = PDNSServer.objects.get(name='test server')
|
||||
test_server.online = False
|
||||
test_server.save()
|
||||
self.assertEqual(test_context.total_servers(),1)
|
||||
self.assertEqual(test_context.online_servers(),0)
|
||||
self.assertEqual(test_context.offline_servers(),1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
0
src/tests/basedata.py
Normal file
0
src/tests/basedata.py
Normal file
Reference in New Issue
Block a user