Refactoring to avoid collisions.
All checks were successful
pda-new unit tests / Run-unit-tests (push) Successful in 1m10s

This commit is contained in:
2025-10-27 22:52:09 +01:00
parent 7df213902e
commit 5e5fe12b5c
4 changed files with 171 additions and 24 deletions

View File

@@ -21,12 +21,17 @@ pip3 install --upgrade pip
pip3 install -f src/requirements.txt
```
## Installation
Run it manually via:
Test if your installation works:
```
python3 src/manage.py test
```
## Installation
Run it manually via:
```
python3 src/manage.py runserver
```
For production environments, gunicorn or a similar UWSGI implementation, preferably using a webserver as a proxy is recommended.

View File

@@ -0,0 +1,45 @@
# Generated by Django 5.2.5 on 2025-10-24 09:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pdns", "0005_pdnsdomain_domain_type"),
]
operations = [
migrations.RenameField(
model_name="pdnsdomain",
old_name="domain_name",
new_name="name",
),
migrations.RenameField(
model_name="pdnsdomain",
old_name="domain_type",
new_name="type",
),
migrations.AddField(
model_name="pdnsdomain",
name="last_loaded",
field=models.DateTimeField(
editable=False, null=True, verbose_name="Last loaded"
),
),
migrations.AddField(
model_name="pdnsdomain",
name="last_notified",
field=models.PositiveIntegerField(
editable=False, null=True, verbose_name="Last notified serial"
),
),
migrations.AddField(
model_name="pdnsdomain",
name="serial",
field=models.PositiveIntegerField(
default=1970010101, verbose_name="Serial"
),
preserve_default=False,
),
]

View File

@@ -0,0 +1,57 @@
# Generated by Django 5.2.5 on 2025-10-27 21:51
import django.core.validators
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("pdns", "0006_rename_domain_name_pdnsdomain_name_and_more"),
]
operations = [
migrations.RenameField(
model_name="pdnsdomain",
old_name="type",
new_name="domain_type",
),
migrations.AlterField(
model_name="pdnsdomain",
name="name",
field=models.CharField(
max_length=250,
validators=[
django.core.validators.DomainNameValidator(
message="Must be a valid domain name."
)
],
verbose_name="Name",
),
),
migrations.CreateModel(
name="PDNSResourceRecord",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("record_type", models.CharField(verbose_name="Type")),
(
"domain",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="records",
to="pdns.pdnsdomain",
verbose_name="Domain",
),
),
],
),
]

View File

@@ -5,26 +5,29 @@
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.
from django.core.validators import DomainNameValidator
# Basic code structure convention for models:
# 1. Meta information
# 2. Data fields
# 3. Functions
# Alphabetical order within each of those categories if
# possible.
"""
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.
"""
"""
Basic code structure convention for models:
1. Meta information
2. Data fields
3. Functions
"""
class PDNSContext(models.Model):
description = models.TextField(verbose_name=_('Description'),
@@ -88,8 +91,10 @@ class PDNSServer(models.Model):
default=False
)
# Depending on the PDNS cluster architecture certain servers
# might not be writeable due to the backend.
"""
Depending on the PDNS cluster architecture certain servers might not
be writeable due to the backend, so we allow for that.
"""
readonly = models.BooleanField(verbose_name=_('Read Only'),
default=False
)
@@ -137,12 +142,47 @@ class PDNSDomain(models.Model):
on_delete=models.CASCADE,
)
domain_name = models.CharField(verbose_name='Name',
name = models.CharField(verbose_name='Name',
max_length=250,
validators=[DomainNameValidator(message=_('Must be a valid domain name.'))]
)
# Avoiding possible collision with the 'type' soft keyword;
# see https://docs.python.org/3/reference/lexical_analysis.html#soft-keywords
domain_type = models.CharField(verbose_name='Type',
choices=DOMAIN_TYPE_CHOICES,
default=DOMAIN_TYPE_CHOICES['NATIVE']
)
"""
##convention## for serials is YYYYMMDDNN with NN being incremented
each time the domain is updated on the same day, but there is no
rule against going 1,2,3,4...
"""
serial = models.PositiveIntegerField(verbose_name=_('Serial'),
)
last_notified = models.PositiveIntegerField(verbose_name=_('Last notified serial'),
editable=False,
null=True
)
last_loaded = models.DateTimeField(verbose_name=_('Last loaded'),
editable=False,
null=True
)
class PDNSResourceRecord(models.Model):
"""
Individual record types will inherit from this and have custom
validators; this base class will serve for any record type we
didn't put in yet.
"""
domain = models.ForeignKey(PDNSDomain, verbose_name=_('Domain'),
on_delete=models.CASCADE,
related_name='records'
)
record_type = models.CharField(verbose_name='Type')