From ddc946b021f66cdb9f310ac8fdf792262669df25 Mon Sep 17 00:00:00 2001 From: Marc Aymerich Date: Wed, 9 Mar 2016 10:06:26 +0000 Subject: [PATCH] Show implicit domain records --- TODO.md | 1 - orchestra/contrib/domains/admin.py | 33 +++++++- orchestra/contrib/domains/models.py | 117 +++++++++++++++++----------- 3 files changed, 101 insertions(+), 50 deletions(-) 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):