diff --git a/binder/admin.py b/binder/admin.py index 7d9de54..90404d4 100644 --- a/binder/admin.py +++ b/binder/admin.py @@ -4,6 +4,7 @@ from models import BindServer, Key from django.contrib import admin from django.forms import ModelForm, ValidationError + class BindServerAdminForm(ModelForm): def clean_statistics_port(self): port = self.cleaned_data["statistics_port"] @@ -13,7 +14,6 @@ class BindServerAdminForm(ModelForm): params={'port': port}) return self.cleaned_data["statistics_port"] - def clean_dns_port(self): port = self.cleaned_data["dns_port"] if port < 1 or port > 65535: @@ -31,7 +31,7 @@ class BindServerAdmin(admin.ModelAdmin): class KeyAdminForm(ModelForm): def clean_data(self): try: - keyring = dns.tsigkeyring.from_text({'': self.cleaned_data["data"]}) + dns.tsigkeyring.from_text({'': self.cleaned_data["data"]}) except binascii.Error as err: raise ValidationError("Invalid key data: %(error)s", params={'error': err}) diff --git a/binder/exceptions.py b/binder/exceptions.py index 7bad101..f05272d 100644 --- a/binder/exceptions.py +++ b/binder/exceptions.py @@ -1,33 +1,35 @@ -### Binder Exceptions +# Binder Exceptions + class TransferException(Exception): - """ - Thrown when an AXFR transfer cannot be performed. - """ + + """Thrown when an AXFR transfer cannot be performed.""" pass + class ZoneException(Exception): - """ - Thrown when there is an issue dealing with a - DNS zone. - """ + + """Thrown when there is an issue dealing with a DNS zone.""" pass + class RecordException(Exception): - """ - Thrown when there is an issue dealign with - a Record. - * Adding or deleting. + + """Thrown when there is an issue dealign with a Record. + + * Adding or deleting. """ pass + class KeyringException(Exception): - """ - Thrown when there is a problem creating the keyring. - * When the length/padding of the TSIG data is incorrect. + + """Thrown when there is a problem creating the keyring. + + * When the length/padding of the TSIG data is incorrect. """ pass diff --git a/binder/forms.py b/binder/forms.py index ef9c040..53fd31c 100644 --- a/binder/forms.py +++ b/binder/forms.py @@ -1,4 +1,4 @@ -### Binder Forms +# Binder Forms # 3rd Party from django import forms @@ -8,10 +8,11 @@ from django.forms import ValidationError # App Imports from models import Key -### Custom Form Fields class CustomUnicodeListField(forms.CharField): - """ Convert unicode item list to list of strings. """ + + """Convert unicode item list to list of strings.""" + def clean(self, value): try: string_list = [str(cur_rr) for cur_rr in eval(value)] @@ -19,12 +20,17 @@ class CustomUnicodeListField(forms.CharField): raise ValidationError("Error in converting Unicode list to list of Strings: %r" % value) return string_list + class CustomStringPeriodSuffix(forms.CharField): - """ Convert unicode to string and make sure period is last character. """ - ### This seems very unclean. Need a better to way to complete the fqdn - ### depending on if it ends in a period. - ### TODO(jforman): Add Regex check in here for valid rr data - ### http://www.zytrax.com/books/dns/apa/names.html + + """Convert unicode to string and make sure period is last character. + + This seems very unclean. Need a better to way to complete the fqdn + depending on if it ends in a period. + TODO(jforman): Add Regex check in here for valid rr data + http://www.zytrax.com/books/dns/apa/names.html + """ + def clean(self, value): try: new_string = str(value) @@ -34,42 +40,60 @@ class CustomStringPeriodSuffix(forms.CharField): raise ValidationError("Unable to stick a period on the end of your input: %r" % value) return new_string -### Form Models + class FormAddForwardRecord(forms.Form): - """ Form used to add a Forward DNS record. """ + + """Form used to add a Forward DNS record.""" + dns_server = forms.CharField(max_length=100) - record_name = forms.RegexField(max_length=100, regex="^[a-zA-Z0-9-_]+$", required=False) + record_name = forms.RegexField(max_length=100, + regex="^[a-zA-Z0-9-_]+$", + required=False) record_type = forms.ChoiceField(choices=settings.RECORD_TYPE_CHOICES) zone_name = forms.CharField(max_length=100) record_data = forms.GenericIPAddressField() ttl = forms.ChoiceField(choices=settings.TTL_CHOICES) create_reverse = forms.BooleanField(required=False) - key_name = forms.ModelChoiceField(queryset=Key.objects.all(), required=False) + key_name = forms.ModelChoiceField(queryset=Key.objects.all(), + required=False) + class FormAddReverseRecord(forms.Form): - """ Form used to add a Reverse (PTR) DNS record. """ + + """Form used to add a Reverse (PTR) DNS record.""" + dns_server = forms.CharField(max_length=100) record_name = forms.IntegerField(min_value=0, max_value=255) - record_type = forms.RegexField(regex=r"^PTR$",error_messages={"invalid" : "The only valid choice here is PTR."}) + record_type = forms.RegexField(regex=r"^PTR$", + error_messages={"invalid": "The only valid choice here is PTR."}) zone_name = forms.CharField(max_length=100) record_data = CustomStringPeriodSuffix(required=True) ttl = forms.ChoiceField(choices=settings.TTL_CHOICES) - key_name = forms.ModelChoiceField(queryset=Key.objects.all(), required=False) + key_name = forms.ModelChoiceField(queryset=Key.objects.all(), + required=False) create_reverse = forms.BooleanField(required=False) + class FormAddCnameRecord(forms.Form): - """ Form used to add a CNAME record. """ + + """Form used to add a CNAME record.""" + dns_server = forms.CharField(max_length=100) originating_record = forms.CharField(max_length=100) cname = forms.RegexField(max_length=100, regex="^[a-zA-Z0-9-_]+$") zone_name = forms.CharField(max_length=256) ttl = forms.ChoiceField(choices=settings.TTL_CHOICES) - key_name = forms.ModelChoiceField(queryset=Key.objects.all(), required=False) + key_name = forms.ModelChoiceField(queryset=Key.objects.all(), + required=False) + class FormDeleteRecord(forms.Form): - """ Final form to delete DNS record(s). """ + + """Final form to delete DNS record(s).""" + dns_server = forms.CharField(max_length=100) zone_name = forms.CharField(max_length=256) rr_list = CustomUnicodeListField() - key_name = forms.ModelChoiceField(queryset=Key.objects.all(), required=False) + key_name = forms.ModelChoiceField(queryset=Key.objects.all(), + required=False) diff --git a/binder/helpers.py b/binder/helpers.py index a2aa9eb..45ea517 100644 --- a/binder/helpers.py +++ b/binder/helpers.py @@ -1,10 +1,8 @@ -### Binder Helpers +# Binder Helpers # Standard Imports -import binascii import re import socket -import sys # 3rd Party import dns.query @@ -14,10 +12,12 @@ import dns.tsigkeyring import dns.update # App Imports -from binder import exceptions, models +from binder import models -def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl, key_name, create_reverse=False): - """ Parse passed elements and determine which records to create. + +def add_record(dns_server, zone_name, record_name, record_type, record_data, + ttl, key_name, create_reverse=False): + """Parse passed elements and determine which records to create. Args: String dns_server @@ -32,19 +32,21 @@ def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl Return: Dict containing {description, output} from record creation """ - response = [] - response.append({ "description" : "Forward Record Creation: %s.%s" % (record_name, zone_name), - "output" : create_update(dns_server, - zone_name, - record_name, - record_type, - record_data, - ttl, - key_name)}) + response.append({"description": "Forward Record Creation: %s.%s" % + (record_name, zone_name), + "output": create_update(dns_server, + zone_name, + record_name, + record_type, + record_data, + ttl, + key_name)}) - """ If requested, create a reverse PTR record. - Given the forward record created, resolve its underlying IP. Use that to create the reverse record. + """If requested, create a reverse PTR record. + + Given the forward record created, resolve its underlying IP. + Use that to create the reverse record. reverse_ip_fqdn ex: 5.0.20.10.in-addr.arpa. reverse_ip: 5 reverse_domain: 0.20.10.in-addr.arpa. @@ -55,20 +57,21 @@ def add_record(dns_server, zone_name, record_name, record_type, record_data, ttl # for this reverse DNS record parsing. reverse_ip = re.search(r"([0-9]+).(.*)$", reverse_ip_fqdn).group(1) reverse_domain = re.search(r"([0-9]+).(.*)$", reverse_ip_fqdn).group(2) - response.append({ "description" : "Reverse Record Creation: %s" % record_data, - "output" : create_update(dns_server, - reverse_domain, - reverse_ip, - "PTR", - "%s.%s." % (record_name, zone_name), - ttl, - key_name)}) + response.append({"description": "Reverse Record Creation: %s" % record_data, + "output": create_update(dns_server, + reverse_domain, + reverse_ip, + "PTR", + "%s.%s." % (record_name, zone_name), + ttl, + key_name)}) return response -def add_cname_record(dns_server, zone_name, cname, originating_record, ttl, key_name): - """Add a Cname record.""" +def add_cname_record(dns_server, zone_name, cname, originating_record, ttl, + key_name): + """Add a CNAME record.""" output = create_update(dns_server, zone_name, cname, @@ -77,12 +80,13 @@ def add_cname_record(dns_server, zone_name, cname, originating_record, ttl, key_ ttl, key_name) - return [{ "description" : "CNAME %s.%s points to %s" % (cname, zone_name, originating_record), - "output" : output}] + return [{"description": "CNAME %s.%s points to %s" % + (cname, zone_name, originating_record), + "output": output}] + def delete_record(dns_server, rr_list, key_name): """Delete a list of DNS records passed as strings in rr_items.""" - server = models.BindServer.objects.get(hostname=dns_server) try: @@ -99,18 +103,24 @@ def delete_record(dns_server, rr_list, key_name): record_list = current_rr.split(".", 1) record = record_list[0] domain = record_list[1] - dns_update = dns.update.Update(domain, keyring=keyring, keyalgorithm=algorithm) + dns_update = dns.update.Update(domain, + keyring=keyring, + keyalgorithm=algorithm) dns_update.delete(record) - output = send_dns_update(dns_update, dns_server, server.dns_port, key_name) + output = send_dns_update(dns_update, + dns_server, + server.dns_port, + key_name) - delete_response.append({ "description" : "Delete Record: %s" % current_rr, - "output" : output }) + delete_response.append({"description": "Delete Record: %s" % current_rr, + "output": output}) return delete_response -def create_update(dns_server, zone_name, record_name, record_type, record_data, ttl, key_name): - """ Update/Create DNS record of name and type with passed data and ttl. """ +def create_update(dns_server, zone_name, record_name, record_type, record_data, + ttl, key_name): + """Update/Create DNS record of name and type with passed data and ttl.""" server = models.BindServer.objects.get(hostname=dns_server) try: @@ -122,14 +132,18 @@ def create_update(dns_server, zone_name, record_name, record_type, record_data, keyring = transfer_key.create_keyring() algorithm = transfer_key.algorithm - dns_update = dns.update.Update(zone_name, keyring=keyring, keyalgorithm=algorithm) + dns_update = dns.update.Update(zone_name, + keyring=keyring, + keyalgorithm=algorithm) dns_update.replace(record_name, ttl, record_type, record_data) output = send_dns_update(dns_update, dns_server, server.dns_port, key_name) return output + def ip_info(host_name): """Create a dictionary mapping address types to their IP's. + If an error is encountered, key to error is "Error". """ info = [] @@ -148,8 +162,9 @@ def ip_info(host_name): return info + def send_dns_update(dns_message, dns_server, port, key_name): - """ Send DNS message to server and return response. + """Send DNS message to server and return response. Args: Update dns_update @@ -159,14 +174,13 @@ def send_dns_update(dns_message, dns_server, port, key_name): Returns: String output """ - try: output = dns.query.tcp(dns_message, dns_server, port=port) except dns.tsig.PeerBadKey: output = ("DNS server %s is not configured for TSIG key: %s." % (dns_server, key_name)) except dns.tsig.PeerBadSignature: - output = ("DNS server %s did like the TSIG signature we sent. Check key %s " - "for correctness." % (dns_server, key_name)) + output = ("DNS server %s did like the TSIG signature we sent. Check " + "key %s for correctness." % (dns_server, key_name)) return output diff --git a/binder/models.py b/binder/models.py index 8083feb..b880967 100644 --- a/binder/models.py +++ b/binder/models.py @@ -3,7 +3,6 @@ # Standard Imports import binascii import socket -import urllib2 # 3rd Party from pybindxml import reader as bindreader @@ -22,20 +21,24 @@ TSIG_ALGORITHMS = (('HMAC-MD5.SIG-ALG.REG.INT', 'MD5'), ('hmac-sha384', 'SHA384'), ('hmac-sha512', 'SHA512')) + class Key(models.Model): - """ Store and reference TSIG keys. + + """Store and reference TSIG keys. TODO: Should/Can we encrypt these DNS keys in the DB? """ + name = models.CharField(max_length=255, unique=True, - help_text="A human readable name for the key to store, used for " - "further references to the key.") + help_text="A human readable name for the key to " + "store, used for further references to the key.") data = models.CharField(max_length=255, help_text="The private part of the TSIG key.") algorithm = models.CharField(max_length=255, choices=TSIG_ALGORITHMS, - help_text="The algorithm which has been used for the key.") + help_text="The algorithm which has been used " + "for the key.") def __unicode__(self): return self.name @@ -56,10 +59,12 @@ class Key(models.Model): class BindServer(models.Model): - """ Store DNS servers and attributes for referencing their - statistics ports. Also reference FK for TSIG transfer keys, - if required. + + """Store DNS servers and attributes for referencing their statistics ports. + + Also reference FK for TSIG transfer keys, if required. """ + hostname = models.CharField(max_length=255, unique=True, help_text="Host name or IP address of the BIND server.") @@ -85,7 +90,7 @@ class BindServer(models.Model): ordering = ["hostname"] def list_zones(self): - """ List the DNS zones and attributes. + """List the DNS zones and attributes. TODO: Parse these XML more intelligently. Grab the view name. Any other data available? @@ -100,7 +105,7 @@ class BindServer(models.Model): return zone_data def list_zone_records(self, zone_name): - """ List all records in a specific zone. + """List all records in a specific zone. TODO: Print out current_record in the loop and see if we can parse this more programatically, rather than just splitting on space. What is the difference between class and type? @@ -110,7 +115,6 @@ class BindServer(models.Model): Returns: List of Dicts { String rr_name, String rr_ttl, String rr_class, String rr_type, String rr_data } """ - try: transfer_key = Key.objects.get(name=self.default_transfer_key) except Key.DoesNotExist: @@ -154,4 +158,3 @@ class BindServer(models.Model): record_array.append(rr_dict) return record_array - diff --git a/binder/tests/disabled_testIntegration.py b/binder/tests/disabled_testIntegration.py index 93ab574..9609fd7 100644 --- a/binder/tests/disabled_testIntegration.py +++ b/binder/tests/disabled_testIntegration.py @@ -2,10 +2,11 @@ from django.core.urlresolvers import reverse from django.test import TestCase from django.test.client import Client -from binder import helpers, models +from binder import models + class Integration_Tests(TestCase): - fixtures = [ "binder/fixtures/binder_test.json" ] + fixtures = ["binder/fixtures/binder_test.json"] def setUp(self): self.client = Client() @@ -13,13 +14,13 @@ class Integration_Tests(TestCase): def test_Integration_Add_Record(self): """Add forward and reverse record on domain1.local.""" - add_dict = { "dns_server" : self.testserver, - "record_name" : "record1", - "record_type" : "A", - "zone_name" : "domain1.local", - "record_data" : "10.254.1.101", - "ttl" : 86400, - "create_reverse" : True} + add_dict = {"dns_server": self.testserver, + "record_name": "record1", + "record_type": "A", + "zone_name": "domain1.local", + "record_data": "10.254.1.101", + "ttl": 86400, + "create_reverse": True} response = self.client.post(reverse("add_record_result"), add_dict) self.assertEqual(response.status_code, 200) # Make sure that we get two responses (fwd/rev) back from the server. @@ -32,10 +33,9 @@ class Integration_Tests(TestCase): def test_Integration_Delete_Record(self): """Delete record1.domain1.local""" - delete_dict = { "dns_server" : self.testserver, - "zone_name" : "domain1.local", - "rr_list" : '[u"record1.domain1.local", u"record2.domain1.local"]', - } + delete_dict = {"dns_server": self.testserver, + "zone_name": "domain1.local", + "rr_list": '[u"record1.domain1.local", u"record2.domain1.local"]'} response = self.client.post(reverse("delete_record_result"), delete_dict) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.context["response"]), 2) @@ -44,16 +44,15 @@ class Integration_Tests(TestCase): self.assertRegexpMatches(dns_update_output, "opcode UPDATE") self.assertRegexpMatches(dns_update_output, "rcode NOERROR") - def test_Integration_Add_Cname(self): - """ Add CNAME cnametest1 after adding associated A record record1.""" - add_dict = { "dns_server" : self.testserver, - "record_name" : "record1", - "record_type" : "A", - "zone_name" : "domain1.local", - "record_data" : "10.254.1.101", - "ttl" : 86400, - "create_reverse" : False} + """Add CNAME cnametest1 after adding associated A record record1.""" + add_dict = {"dns_server": self.testserver, + "record_name": "record1", + "record_type": "A", + "zone_name": "domain1.local", + "record_data": "10.254.1.101", + "ttl": 86400, + "create_reverse": False} response = self.client.post(reverse("add_record_result"), add_dict) self.assertEqual(response.status_code, 200) # Make sure that we get two responses (fwd/rev) back from the server. @@ -64,19 +63,17 @@ class Integration_Tests(TestCase): self.assertRegexpMatches(dns_update_output, "opcode UPDATE") self.assertRegexpMatches(dns_update_output, "rcode NOERROR") - cname_dict = { "dns_server" : self.testserver, - "originating_record" : "record1.domain1.local", - "cname" : "cnametest1", - "zone_name" : "domain1.local", - "ttl" : 86400, - } + cname_dict = {"dns_server": self.testserver, + "originating_record": "record1.domain1.local", + "cname": "cnametest1", + "zone_name": "domain1.local", + "ttl": 86400} response = self.client.post(reverse("add_cname_result"), cname_dict) self.assertEqual(response.status_code, 200) for current_response in response.context["response"]: dns_update_output = str(current_response["output"]) self.assertRegexpMatches(dns_update_output, "opcode UPDATE") self.assertRegexpMatches(dns_update_output, "rcode NOERROR") - def test_Integration_ServerZoneList_ConnectionRefused(self): """Confirm connection refused on a server zone list.""" @@ -94,11 +91,14 @@ class Integration_Tests(TestCase): def test_Integration_ZoneList_MissingTransferKey(self): """Attempt to list a zone's records with missing TSIG key. + domain3.local should be configured to require a TSIG key - for transfers.""" + for transfers. + """ dns_server = models.BindServer.objects.get(hostname="testserver1") response = self.client.get(reverse("zone_list", args=("testserver1", "domain3.local"))) self.assertEqual(response.status_code, 200) self.assertEqual(response.context["zone_name"], "domain3.local") self.assertEqual(response.context["dns_server"], "testserver1") - self.assertRegexpMatches(str(response.context["errors"]), "Unable to perform AXFR to list zone records. Did you forget to specify a default transfer key?") + self.assertRegexpMatches(str(response.context["errors"]), + "Unable to perform AXFR to list zone records. Did you forget to specify a default transfer key?") diff --git a/binder/tests/testForms.py b/binder/tests/testForms.py index 5834e36..06373b7 100644 --- a/binder/tests/testForms.py +++ b/binder/tests/testForms.py @@ -2,56 +2,55 @@ from django.test import TestCase from binder import forms + class Form_Tests(TestCase): def test_Valid_FormAddRecord(self): """Test FormAddRecord with valid data, with/without create_reverse.""" - form_data = {"dns_server":"server1", - "record_name":"record1", - "record_type":"A", - "zone_name":"domain.local", - "record_data":"10.254.254.254", - "ttl":3600, + form_data = {"dns_server": "server1", + "record_name": "record1", + "record_type": "A", + "zone_name": "domain.local", + "record_data": "10.254.254.254", + "ttl": 3600, "key_name": None, - "create_reverse" : False} + "create_reverse": False} testform_1 = forms.FormAddForwardRecord(form_data) self.assertTrue(testform_1.is_valid()) - form_data = {"dns_server":"server1", - "record_name":"record1", - "record_type":"A", - "zone_name":"domain.local", - "record_data":"10.254.254.254", - "ttl":3600, - "key_name":None, - "create_reverse":True} + form_data = {"dns_server": "server1", + "record_name": "record1", + "record_type": "A", + "zone_name": "domain.local", + "record_data": "10.254.254.254", + "ttl": 3600, + "key_name": None, + "create_reverse": True} testform_2 = forms.FormAddForwardRecord(form_data) self.assertTrue(testform_2.is_valid()) - form_data = { "dns_server" : "server1", - "record_name" : 41, - "record_type" : "PTR", - "zone_name" : "1.254.10.in-addr.arpa", - "record_data" : "reverse41.domain1.local", - "ttl" : 3600, - "key_name" : None } + form_data = {"dns_server": "server1", + "record_name": 41, + "record_type": "PTR", + "zone_name": "1.254.10.in-addr.arpa", + "record_data": "reverse41.domain1.local", + "ttl": 3600, + "key_name": None} reverseform_1 = forms.FormAddReverseRecord(form_data) reverseform_1.is_valid() self.assertTrue(reverseform_1.is_valid()) - - def test_MissingData_FormAddRecord(self): - """ Submit FormAddRecord with missing record_data.""" - form_data = {"dns_server":"server1", - "record_name":"record1", + """Submit FormAddRecord with missing record_data.""" + form_data = {"dns_server": "server1", + "record_name": "record1", "record_type": "A", - "zone_name":"domain.local", - "record_data":"", + "zone_name": "domain.local", + "record_data": "", "ttl": 300, - "key_name":None, - "create_reverse":True} + "key_name": None, + "create_reverse": True} expected_form_errors = {"record_data": [u"This field is required."]} testform = forms.FormAddForwardRecord(form_data) @@ -60,15 +59,15 @@ class Form_Tests(TestCase): self.assertEquals(expected_form_errors, testform.errors) def test_InvalidValue_FormAddRecord(self): - """ Pass FormAddRecord invalid values, compare error response dicts.""" - form_data = {"dns_server":"server1", - "record_name":"record1$$$", - "record_type":123, - "zone_name":"domain.local", - "record_data":"A.B.C.D", - "ttl":"A", - "key_name":None, - "create_reverse":True} + """Pass FormAddRecord invalid values, compare error response dicts.""" + form_data = {"dns_server": "server1", + "record_name": "record1$$$", + "record_type": 123, + "zone_name": "domain.local", + "record_data": "A.B.C.D", + "ttl": "A", + "key_name": None, + "create_reverse": True} expected_form_errors = {"record_data": [u"Enter a valid IPv4 or IPv6 address."], "record_name": [u"Enter a valid value."], @@ -81,10 +80,9 @@ class Form_Tests(TestCase): def test_Validation_FormDeleteRecord(self): """Validate good data in the FormDeleteRecord form.""" - delete_dict = { "dns_server" : "foo.net", - "zone_name" : "domain1.local", - "rr_list" : '[u"record1.domain1.local", u"record2.domain1.local"]', - } + delete_dict = {"dns_server": "foo.net", + "zone_name": "domain1.local", + "rr_list": '[u"record1.domain1.local", u"record2.domain1.local"]'} testform_1 = forms.FormDeleteRecord(delete_dict) testform_1.is_valid self.assertFalse(testform_1.errors) @@ -95,12 +93,12 @@ class Form_Tests(TestCase): def test_MissingName_AddCnameForm(self): """Attempt to submit a cname add form missing the cname value.""" - form_dict = { "dns_server" : "testserver1", - "zone_name" : "domain1.local", - "originating_record" : "record1.domain1.local", - "cname" : "", - "ttl" : 300 } - expected_form_errors = { "cname" : [u"This field is required."] } + form_dict = {"dns_server": "testserver1", + "zone_name": "domain1.local", + "originating_record": "record1.domain1.local", + "cname": "", + "ttl": 300} + expected_form_errors = {"cname": [u"This field is required."]} testform_1 = forms.FormAddCnameRecord(form_dict) testform_1.is_valid() self.assertTrue(testform_1.errors) diff --git a/binder/tests/testModels.py b/binder/tests/testModels.py index 20bf359..5828888 100644 --- a/binder/tests/testModels.py +++ b/binder/tests/testModels.py @@ -3,6 +3,7 @@ from django.db import IntegrityError from binder import models + class Model_BindServer_Tests(TestCase): def test_BindServerModel(self): """Test that adding a well-formed BindServer works.""" @@ -28,7 +29,7 @@ class Model_BindServer_Tests(TestCase): class Model_Key_Tests(TestCase): def test_KeyModel(self): - """ Test that adding a well-formed Key works.""" + """Test that adding a well-formed Key works.""" self.assertEqual(models.Key.objects.count(), 0) key_1 = models.Key(name="testkey1", data="abc123", @@ -38,4 +39,4 @@ class Model_Key_Tests(TestCase): def test_NonExistantKey(self): with self.assertRaisesMessage(models.Key.DoesNotExist, "Key matching query does not exist"): - this_key = models.Key.objects.get(name="does_not_exist") + models.Key.objects.get(name="does_not_exist") diff --git a/binder/tests/testViews.py b/binder/tests/testViews.py index c2a34c3..3513749 100644 --- a/binder/tests/testViews.py +++ b/binder/tests/testViews.py @@ -2,11 +2,13 @@ from django.test import TestCase from django.test.client import Client from django.core.urlresolvers import reverse -from binder import models, helpers +from binder import models class GetTests(TestCase): - """ Unit Tests that exercise HTTP GET. """ + + """Unit Tests that exercise HTTP GET.""" + def setUp(self): self.client = Client() @@ -19,7 +21,7 @@ class GetTests(TestCase): self.assertEqual(response.status_code, 200) def test_GetResultRedirects(self): - """ GETing a /result/ URL should always redirect to /. """ + """GETing a /result/ URL should always redirect to /.""" response = self.client.get(reverse("add_record_result"), follow=True) self.assertRedirects(response, reverse("index")) self.assertEqual(response.status_code, 200) @@ -31,25 +33,28 @@ class GetTests(TestCase): self.assertEqual(response.status_code, 200) def test_GetInvalidServer(self): - """ Get a zone list for a server not in the database.""" + """Get a zone list for a server not in the database.""" server_name = "unconfigured.server.net" - response = self.client.get(reverse("server_zone_list", args=(server_name, ))) + response = self.client.get(reverse("server_zone_list", + args=(server_name, ))) self.assertEqual(response.status_code, 404) class PostTests(TestCase): - """ Unit Tests that exercise HTTP POST. """ + + """Unit Tests that exercise HTTP POST.""" + def setUp(self): self.client = Client() models.BindServer(hostname="testserver.test.net", statistics_port=1234).save() - def test_DeleteRecordInitial_Empty(self): - """ Ensure the initial deletion form works as expected with no RR list. """ - response = self.client.post(reverse("delete_record"), { "dns_server" : "testserver.test.net", - "zone_name" : "testzone1.test.net", - "rr_list" : [] }) + """Ensure the initial deletion form works as expected with no RR list.""" + response = self.client.post(reverse("delete_record"), + {"dns_server": "testserver.test.net", + "zone_name": "testzone1.test.net", + "rr_list": []}) self.assertContains(response, '', @@ -63,11 +68,11 @@ class PostTests(TestCase): def test_DeleteRecordInitial(self): - """ Ensure the initial deletion form works as expected with RRs mentioned. """ - response = self.client.post(reverse("delete_record"), {"dns_server" : "testserver.test.net", - "zone_name" : "testzone1.test.net", - "rr_list" : ["testrecord1.testzone1.test.net", - "testrecord2.testzone1.test.net"] }) + """Ensure the initial deletion form works as expected with RRs mentioned.""" + response = self.client.post(reverse("delete_record"), {"dns_server": "testserver.test.net", + "zone_name": "testzone1.test.net", + "rr_list": ["testrecord1.testzone1.test.net", + "testrecord2.testzone1.test.net"]}) self.assertContains(response, '', html=True) self.assertContains(response, diff --git a/binder/urls.py b/binder/urls.py index 97c5130..ad1994b 100644 --- a/binder/urls.py +++ b/binder/urls.py @@ -1,6 +1,4 @@ from django.conf.urls import patterns, include, url -from django.core.urlresolvers import reverse - from django.contrib import admin admin.autodiscover() diff --git a/binder/views.py b/binder/views.py index d97b1d6..f952ca6 100644 --- a/binder/views.py +++ b/binder/views.py @@ -1,4 +1,4 @@ -### Binder VIews +# Binder VIews # 3rd Party from django.conf import settings @@ -7,24 +7,26 @@ from django.shortcuts import get_object_or_404, redirect, render # App Imports from binder import exceptions, forms, helpers, models + def home_index(request): - """ List the main index page for Binder. """ + """List the main index page for Binder.""" return render(request, "index.html") def view_server_list(request): - """ List the DNS servers configured in the database. """ + """List the DNS servers configured in the database.""" server_list = models.BindServer.objects.all().order_by("hostname") server_info = [] for current in server_list: - server_info.append({"host_name" : current, "ip_address" : helpers.ip_info(current.hostname)}) + server_info.append({"host_name": current, + "ip_address": helpers.ip_info(current.hostname)}) return render(request, "bcommon/list_servers.html", - { "server_info" : server_info}) + {"server_info": server_info}) def view_server_zones(request, dns_server): - """ Display the list of DNS zones a particular DNS host provides. """ + """Display the list of DNS zones a particular DNS host provides.""" errors = "" zone_array = {} @@ -36,13 +38,13 @@ def view_server_zones(request, dns_server): errors = "Unable to list server zones. Error: %s" % err return render(request, "bcommon/list_server_zones.html", - { "errors" : errors, - "dns_server" : this_server, - "zone_array" : zone_array}) + {"errors": errors, + "dns_server": this_server, + "zone_array": zone_array}) def view_zone_records(request, dns_server, zone_name): - """ Display the list of records for a particular zone. """ + """Display the list of records for a particular zone.""" errors = "" zone_array = {} @@ -52,32 +54,31 @@ def view_zone_records(request, dns_server, zone_name): zone_array = this_server.list_zone_records(zone_name) except exceptions.TransferException, err: return render(request, "bcommon/list_zone.html", - { "errors" : err, - "zone_name" : zone_name, - "dns_server" : this_server}) + {"errors": err, + "zone_name": zone_name, + "dns_server": this_server}) return render(request, "bcommon/list_zone.html", - { "zone_array" : zone_array, - "dns_server" : this_server, - "zone_name" : zone_name, - "errors" : errors}) + {"zone_array": zone_array, + "dns_server": this_server, + "zone_name": zone_name, + "errors": errors}) def view_add_record(request, dns_server, zone_name): - """ View to provide form to add a DNS record. """ + """View to provide form to add a DNS record.""" this_server = get_object_or_404(models.BindServer, hostname=dns_server) return render(request, "bcommon/add_record_form.html", - { "dns_server" : this_server, - "zone_name" : zone_name, - "tsig_keys" : models.Key.objects.all(), - "ttl_choices": settings.TTL_CHOICES, - "record_type_choices": settings.RECORD_TYPE_CHOICES, - }) + {"dns_server": this_server, + "zone_name": zone_name, + "tsig_keys": models.Key.objects.all(), + "ttl_choices": settings.TTL_CHOICES, + "record_type_choices": settings.RECORD_TYPE_CHOICES}) def view_add_record_result(request): - """ Process the input given to add a DNS record. """ + """Process the input given to add a DNS record.""" errors = "" if request.method == "GET": return redirect("/") @@ -108,36 +109,35 @@ def view_add_record_result(request): errors = err return render(request, "bcommon/response_result.html", - { "errors" : errors, - "response" : response }) + {"errors": errors, + "response": response}) dns_server = models.BindServer.objects.get(hostname=request.POST["dns_server"]) return render(request, "bcommon/add_record_form.html", - { "dns_server" : dns_server, - "zone_name" : request.POST["zone_name"], - "tsig_keys" : models.Key.objects.all(), - "ttl_choices": settings.TTL_CHOICES, - "record_type_choices": settings.RECORD_TYPE_CHOICES, - "form_errors" : form.errors, - "form_data" : request.POST }) + {"dns_server": dns_server, + "zone_name": request.POST["zone_name"], + "tsig_keys": models.Key.objects.all(), + "ttl_choices": settings.TTL_CHOICES, + "record_type_choices": settings.RECORD_TYPE_CHOICES, + "form_errors": form.errors, + "form_data": request.POST}) def view_add_cname_record(request, dns_server, zone_name, record_name): - """ Process given input to add a CNAME pointer.""" - + """Process given input to add a CNAME pointer.""" this_server = get_object_or_404(models.BindServer, hostname=dns_server) return render(request, "bcommon/add_cname_record_form.html", - { "dns_server" : this_server, - "originating_record" : "%s.%s" % (record_name, zone_name), - "zone_name" : zone_name, - "ttl_choices": settings.TTL_CHOICES, - "tsig_keys" : models.Key.objects.all() }) + {"dns_server": this_server, + "originating_record": "%s.%s" % (record_name, zone_name), + "zone_name": zone_name, + "ttl_choices": settings.TTL_CHOICES, + "tsig_keys": models.Key.objects.all()}) def view_add_cname_result(request): - """ Process input on the CNAME form and provide a response.""" + """Process input on the CNAME form and provide a response.""" if request.method == "GET": return redirect("/") @@ -158,24 +158,24 @@ def view_add_cname_result(request): errors = err return render(request, "bcommon/response_result.html", - {"response" : add_cname_response, - "errors" : errors }) + {"response": add_cname_response, + "errors": errors}) dns_server = models.BindServer.objects.get(hostname=request.POST["dns_server"]) return render(request, "bcommon/add_cname_record_form.html", - { "dns_server" : dns_server, - "zone_name" : request.POST["zone_name"], - "record_name" : request.POST["cname"], - "originating_record" : request.POST["originating_record"], - "form_data" : request.POST, - "form_errors" : form.errors, - "ttl_choices": settings.TTL_CHOICES, - "tsig_keys" : models.Key.objects.all() }) + {"dns_server": dns_server, + "zone_name": request.POST["zone_name"], + "record_name": request.POST["cname"], + "originating_record": request.POST["originating_record"], + "form_data": request.POST, + "form_errors": form.errors, + "ttl_choices": settings.TTL_CHOICES, + "tsig_keys": models.Key.objects.all()}) def view_delete_record(request): - """ Provide the initial form for deleting records. """ + """Provide the initial form for deleting records.""" if request.method == "GET": return redirect("/") @@ -184,14 +184,14 @@ def view_delete_record(request): rr_list = request.POST.getlist("rr_list") return render(request, "bcommon/delete_record_initial.html", - { "dns_server" : dns_server, - "zone_name" : zone_name, - "rr_list" : rr_list, - "tsig_keys" : models.Key.objects.all() }) + {"dns_server": dns_server, + "zone_name": zone_name, + "rr_list": rr_list, + "tsig_keys": models.Key.objects.all()}) def view_delete_result(request): - """ View that deletes records and returns the response. """ + """View that deletes records and returns the response.""" if request.method == "GET": return redirect("/") @@ -209,4 +209,4 @@ def view_delete_result(request): clean_form["key_name"]) return render(request, "bcommon/response_result.html", - { "response" : delete_result }) + {"response": delete_result}) diff --git a/wsgi.py b/wsgi.py index 6d445c1..bc56fdb 100644 --- a/wsgi.py +++ b/wsgi.py @@ -8,7 +8,6 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ """ import os -import sys os.environ.setdefault("DJANGO_SETTINGS_MODULE", "binder.settings") from django.core.wsgi import get_wsgi_application