diff --git a/TODO.md b/TODO.md
index b082725d..ee444c49 100644
--- a/TODO.md
+++ b/TODO.md
@@ -415,7 +415,6 @@ mkhomedir_helper or create ssh homes with bash.rc and such
# get_context signal to overridaconfiguration? best practice: all context on get_context, ever use other context. template rendering as backend generator: proof of concept
-# DOmain show implicit records
# if not database_ready(): schedule a retry in 60 seconds, otherwise resources and other dynamic content gets fucked, maybe attach some 'signal' when first query goes trough
with database_ready:
shit_happend, otherwise schedule for first query
diff --git a/orchestra/contrib/domains/admin.py b/orchestra/contrib/domains/admin.py
index e735c1da..c24c62fc 100644
--- a/orchestra/contrib/domains/admin.py
+++ b/orchestra/contrib/domains/admin.py
@@ -9,6 +9,7 @@ from orchestra.contrib.accounts.admin import AccountAdminMixin
from orchestra.utils import apps
from orchestra.utils.html import get_on_site_link
+from . import settings
from .actions import view_zone, edit_records, set_soa
from .filters import TopDomainListFilter
from .forms import RecordForm, RecordInlineFormSet, BatchDomainCreationAdminForm
@@ -51,8 +52,8 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
'structured_name', 'display_is_top', 'display_websites', 'account_link'
)
add_fields = ('name', 'account')
- fields = ('name', 'account_link')
- readonly_fields = ('account_link', 'top_link',)
+ fields = ('name', 'account_link', 'display_websites')
+ readonly_fields = ('account_link', 'top_link', 'display_websites', 'implicit_records')
inlines = (RecordInline, DomainInline)
list_filter = (TopDomainListFilter,)
change_readonly_fields = ('name', 'serial')
@@ -96,10 +97,38 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
display_websites.short_description = _("Websites")
display_websites.allow_tags = True
+ def implicit_records(self, domain):
+ defaults = []
+ types = set(domain.records.values_list('type', flat=True))
+ ttl = settings.DOMAINS_DEFAULT_TTL
+ lines = []
+ for record in domain.get_default_records():
+ line = '{name} {ttl} IN {type} {value}'.format(
+ name=domain.name,
+ ttl=ttl,
+ type=record.type,
+ value=record.value
+ )
+ if not domain.record_is_implicit(record, types):
+ line = '%s' % line
+ if record.type is Record.SOA:
+ lines.insert(0, line)
+ else:
+ lines.append(line)
+ return '
'.join(lines)
+ implicit_records.short_description = _("Implicit records")
+ implicit_records.allow_tags = True
+
def get_fieldsets(self, request, obj=None):
""" Add SOA fields when domain is top """
fieldsets = super(DomainAdmin, self).get_fieldsets(request, obj)
if obj:
+ fieldsets += (
+ (_("Implicit records"), {
+ 'classes': ('collapse',),
+ 'fields': ('implicit_records',),
+ }),
+ )
if obj.is_top:
fieldsets += (
(_("SOA"), {
diff --git a/orchestra/contrib/domains/models.py b/orchestra/contrib/domains/models.py
index 05aac373..98fde905 100644
--- a/orchestra/contrib/domains/models.py
+++ b/orchestra/contrib/domains/models.py
@@ -153,11 +153,73 @@ class Domain(models.Model):
self.serial = serial
self.save(update_fields=('serial',))
+ def get_default_soa(self):
+ return ' '.join([
+ "%s." % settings.DOMAINS_DEFAULT_NAME_SERVER,
+ utils.format_hostmaster(settings.DOMAINS_DEFAULT_HOSTMASTER),
+ str(self.serial),
+ self.refresh or settings.DOMAINS_DEFAULT_REFRESH,
+ self.retry or settings.DOMAINS_DEFAULT_RETRY,
+ self.expire or settings.DOMAINS_DEFAULT_EXPIRE,
+ self.min_ttl or settings.DOMAINS_DEFAULT_MIN_TTL,
+ ])
+
+ def get_default_records(self):
+ defaults = []
+ if self.is_top:
+ for ns in settings.DOMAINS_DEFAULT_NS:
+ defaults.append(AttrDict(
+ type=Record.NS,
+ value=ns
+ ))
+ soa = self.get_default_soa()
+ defaults.insert(0, AttrDict(
+ type=Record.SOA,
+ value=soa
+ ))
+ for mx in settings.DOMAINS_DEFAULT_MX:
+ defaults.append(AttrDict(
+ type=Record.MX,
+ value=mx
+ ))
+ default_a = settings.DOMAINS_DEFAULT_A
+ if default_a:
+ defaults.append(AttrDict(
+ type=Record.A,
+ value=default_a
+ ))
+ default_aaaa = settings.DOMAINS_DEFAULT_AAAA
+ if default_aaaa:
+ defaults.append(AttrDict(
+ type=Record.AAAA,
+ value=default_aaaa
+ ))
+ return defaults
+
+ def record_is_implicit(self, record, types):
+ if record.type not in types:
+ if record.type is Record.NS:
+ if self.is_top:
+ return True
+ elif record.type is Record.SOA:
+ if self.is_top:
+ return True
+ else:
+ has_a = Record.A in types
+ has_aaaa = Record.AAAA in types
+ is_host = self.is_top or not types or has_a or has_aaaa
+ if is_host:
+ if record.type is Record.MX:
+ return True
+ elif not has_a and not has_aaaa:
+ return True
+ return False
+
def get_records(self):
- types = {}
+ types = set()
records = utils.RecordStorage()
for record in self.get_declared_records():
- types[record.type] = True
+ types.add(record.type)
if record.type == record.SOA:
# Update serial and insert at 0
value = record.value.split()
@@ -173,51 +235,12 @@ class Domain(models.Model):
ttl=record.get_ttl(),
value=record.value
))
- if self.is_top:
- if Record.NS not in types:
- for ns in settings.DOMAINS_DEFAULT_NS:
- records.append(AttrDict(
- type=Record.NS,
- value=ns
- ))
- if Record.SOA not in types:
- soa = [
- "%s." % settings.DOMAINS_DEFAULT_NAME_SERVER,
- utils.format_hostmaster(settings.DOMAINS_DEFAULT_HOSTMASTER),
- str(self.serial),
- self.refresh or settings.DOMAINS_DEFAULT_REFRESH,
- self.retry or settings.DOMAINS_DEFAULT_RETRY,
- self.expire or settings.DOMAINS_DEFAULT_EXPIRE,
- self.min_ttl or settings.DOMAINS_DEFAULT_MIN_TTL,
- ]
- records.insert(0, AttrDict(
- type=Record.SOA,
- value=' '.join(soa)
- ))
- has_a = Record.A in types
- has_aaaa = Record.AAAA in types
- is_host = self.is_top or not types or has_a or has_aaaa
- if is_host:
- if Record.MX not in types:
- for mx in settings.DOMAINS_DEFAULT_MX:
- records.append(AttrDict(
- type=Record.MX,
- value=mx
- ))
- # A and AAAA point to the same default host
- if not has_a and not has_aaaa:
- default_a = settings.DOMAINS_DEFAULT_A
- if default_a:
- records.append(AttrDict(
- type=Record.A,
- value=default_a
- ))
- default_aaaa = settings.DOMAINS_DEFAULT_AAAA
- if default_aaaa:
- records.append(AttrDict(
- type=Record.AAAA,
- value=default_aaaa
- ))
+ for record in self.get_default_records():
+ if self.record_is_implicit(record, types):
+ if record.type is Record.SOA:
+ records.insert(0, record)
+ else:
+ records.append(record)
return records
def render_records(self):