def test_add_delegations_adds_nsrrset_and_glue_in_depth(self): parent = factory.make_Domain() name = factory.make_name() child = factory.make_Domain(name="%s.%s" % (name, parent.name)) default_name = Domain.objects.get_default_domain().name g_name = factory.make_name() grandchild = factory.make_Domain(name="%s.%s" % (g_name, child.name)) dnsrr = factory.make_DNSResource(name="@", domain=child) nsname = factory.make_name() factory.make_DNSData( dnsresource=dnsrr, rrtype="NS", rrdata="%s.%s." % (nsname, grandchild.name), ) nsrr = factory.make_DNSResource(name=nsname, domain=grandchild) other_name = factory.make_name() factory.make_DNSResource(name=other_name, domain=parent) factory.make_DNSData( dnsresource=dnsrr, rrtype="NS", rrdata="%s.%s." % (other_name, parent.name), ) mappings = lazydict(get_hostname_dnsdata_mapping) mapping = mappings[parent] expected_map = { name: HostnameRRsetMapping( rrset={ (30, "NS", default_name), (30, "NS", "%s.%s." % (nsname, grandchild.name)), (30, "NS", "%s.%s." % (other_name, parent.name)), } ) } ns_part = "%s.%s" % (nsname, g_name) for sip in nsrr.ip_addresses.all(): if IPAddress(sip.ip).version == 6: expected_map[ns_part] = HostnameRRsetMapping( rrset={(30, "AAAA", sip.ip)} ) else: expected_map[ns_part] = HostnameRRsetMapping( rrset={(30, "A", sip.ip)} ) parent.add_delegations(mapping, default_name, [IPAddress("::1")], 30) self.assertEqual(expected_map, mapping)
def test_read(self): dnsdata = factory.make_DNSData() for _ in range(3): factory.make_DNSData() uri = get_dnsresourcerecord_uri(dnsdata) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_dnsresource = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( parsed_dnsresource, ContainsDict({ "id": Equals(dnsdata.id), "fqdn": Equals(dnsdata.fqdn), "rrtype": Equals(dnsdata.rrtype), "rrdata": Equals(dnsdata.rrdata), }))
def test_update_admin_only(self): dnsdata = factory.make_DNSData() new_ttl = random.randint(10, 100) uri = get_dnsresourcerecord_uri(dnsdata) response = self.client.put(uri, { "ttl": new_ttl, }) self.assertEqual(http.client.FORBIDDEN, response.status_code, response.content)
def test_admin_admin_returns_dnsdata(self): admin = factory.make_admin() dnsdata = factory.make_DNSData() self.assertEqual( dnsdata, DNSData.objects.get_dnsdata_or_404( dnsdata.id, admin, NodePermission.admin ), )
def test_read_with_type(self): for _ in range(10): factory.make_DNSData() rrtype = DNSData.objects.first().rrtype uri = get_dnsresources_uri() response = self.client.get( uri, {'rrtype': [rrtype]}) self.assertEqual( http.client.OK, response.status_code, response.content) expected_ids = [ dnsrr.id for dnsrr in DNSResource.objects.filter( dnsdata__rrtype=rrtype)] result_ids = [ dnsresource["id"] for dnsresource in json.loads( response.content.decode(settings.DEFAULT_CHARSET)) ] self.assertItemsEqual(expected_ids, result_ids)
def test_get_hostname_dnsdata_mapping_returns_mapping(self): domain = Domain.objects.get_default_domain() expected_mapping = {} # Create 3 labels with 0-5 resources each, verify that they # Come back correctly. for _ in range(3): name = factory.make_name("label") dnsrr = factory.make_DNSResource( name=name, domain=domain, no_ip_addresses=True ) for count in range(random.randint(1, 5)): factory.make_DNSData(dnsresource=dnsrr, ip_addresses=True) expected_mapping.update(self.make_mapping(dnsrr)) # Add one resource to the domain which has no data, so it should not be # in the returned mapping. factory.make_DNSResource(domain=domain, no_ip_addresses=True) actual = DNSData.objects.get_hostname_dnsdata_mapping(domain) self.assertEqual(expected_mapping, actual)
def test__delete_dnsdata(self): user = factory.make_admin() handler = DomainHandler(user, {}, None) domain = factory.make_Domain() dnsresource = factory.make_DNSResource(domain=domain) dnsdata = factory.make_DNSData(dnsresource) handler.delete_dnsdata({"domain": domain.id, "dnsdata_id": dnsdata.id}) dnsdata = reload_object(dnsdata) self.assertThat(dnsdata, Is(None))
def test_user_view_returns_dnsdata(self): user = factory.make_User() dnsdata = factory.make_DNSData() self.assertEqual( dnsdata, DNSData.objects.get_dnsdata_or_404( dnsdata.id, user, NodePermission.view ), )
def test_read(self): domain = factory.make_Domain() for _ in range(3): factory.make_DNSData(domain=domain) uri = get_domain_uri(domain) response = self.client.get(uri) self.assertEqual(http.client.OK, response.status_code, response.content) parsed_domain = json.loads( response.content.decode(settings.DEFAULT_CHARSET)) self.assertThat( parsed_domain, ContainsDict({ "id": Equals(domain.id), "name": Equals(domain.get_name()), "resource_record_count": Equals(3), }), )
def test_returns_interface_ips_but_no_nulls(self): default_domain = Domain.objects.get_default_domain().name domain = factory.make_Domain(name='henry') subnet = factory.make_Subnet(cidr=str(IPNetwork("10/29").cidr)) subnet.gateway_ip = str(IPAddress(IPNetwork(subnet.cidr).ip + 1)) subnet.save() # Create a node with two interfaces, with NULL ips node = factory.make_Node_with_Interface_on_Subnet( subnet=subnet, vlan=subnet.vlan, fabric=subnet.vlan.fabric, domain=domain, interface_count=3) dnsdata = factory.make_DNSData(domain=domain) boot_iface = node.boot_interface interfaces = list(node.interface_set.all().exclude(id=boot_iface.id)) # Now go add IP addresses to the boot interface, and one other boot_ip = factory.make_StaticIPAddress(interface=boot_iface, subnet=subnet) sip = factory.make_StaticIPAddress(interface=interfaces[0], subnet=subnet) default_ttl = random.randint(10, 300) Config.objects.set_config('default_dns_ttl', default_ttl) zones = ZoneGenerator(domain, subnet, default_ttl=default_ttl, serial=random.randint(0, 65535)).as_list() self.assertThat( zones, MatchesSetwise(forward_zone("henry"), reverse_zone(default_domain, "10/29"), reverse_zone(default_domain, "10/24"))) self.assertEqual( { node.hostname: HostnameIPMapping(node.system_id, default_ttl, {'%s' % boot_ip.ip}, node.node_type), "%s.%s" % (interfaces[0].name, node.hostname): HostnameIPMapping(node.system_id, default_ttl, {'%s' % sip.ip}, node.node_type) }, zones[0]._mapping) self.assertEqual({ dnsdata.dnsresource.name: HostnameRRsetMapping( None, {(default_ttl, dnsdata.rrtype, dnsdata.rrdata)}) }.items(), zones[0]._other_mapping.items()) self.assertEqual( { node.fqdn: HostnameIPMapping(node.system_id, default_ttl, {'%s' % boot_ip.ip}, node.node_type), '%s.%s' % (interfaces[0].name, node.fqdn): HostnameIPMapping(node.system_id, default_ttl, {'%s' % sip.ip}, node.node_type) }, zones[1]._mapping) self.assertEqual({}, zones[2]._mapping)
def test_user_admin_raises_PermissionError(self): user = factory.make_User() dnsdata = factory.make_DNSData() self.assertRaises( PermissionDenied, DNSData.objects.get_dnsdata_or_404, dnsdata.id, user, NodePermission.admin, )
def test_delete_deletes_dnsresource_if_no_data(self): self.become_admin() dnsdata = factory.make_DNSData() dnsrr = dnsdata.dnsresource uri = get_dnsresourcerecord_uri(dnsdata) response = self.client.delete(uri) self.assertEqual(http.client.NO_CONTENT, response.status_code, response.content) self.assertIsNone(reload_object(dnsdata)) self.assertIsNone(reload_object(dnsrr))
def test_get_hostname_dnsdata_mapping_returns_raw_ttl(self): # We create 2 domains, one with a ttl, one withoout. # Within each domain, create an RRset with and without ttl. # We then query with raw_ttl=True, and confirm that nothing is # inherited. global_ttl = random.randint(1, 99) Config.objects.set_config('default_dns_ttl', global_ttl) domains = [ factory.make_Domain(), factory.make_Domain(ttl=random.randint(100, 199)) ] for dom in domains: factory.make_DNSData(domain=dom) factory.make_DNSData(domain=dom, ttl=random.randint(200, 299)) expected_mapping = {} for dnsrr in dom.dnsresource_set.all(): expected_mapping.update(self.make_mapping(dnsrr, raw_ttl=True)) actual = DNSData.objects.get_hostname_dnsdata_mapping(dom, raw_ttl=True) self.assertEqual(expected_mapping, actual)
def test_allows_multiple_records_unless_cname(self): dnsdata = factory.make_DNSData(no_ip_addresses=True) if dnsdata.rrtype == "CNAME": with ExpectedException( ValidationError, re.escape("{'__all__': ['%s']}" % MULTI_CNAME_MSG), ): factory.make_DNSData( dnsresource=dnsdata.dnsresource, rrtype="CNAME" ) else: factory.make_DNSData( dnsresource=dnsdata.dnsresource, rrtype=dnsdata.rrtype ) self.assertEqual( 2, DNSData.objects.filter( dnsresource=dnsdata.dnsresource ).count(), )
def test_get_hostname_dnsdata_mapping_contains_node_and_non_node(self): node = factory.make_Node(interface=True) dnsdata1 = factory.make_DNSData( name=node.hostname, domain=node.domain, rrtype="MX" ) dnsdata2 = factory.make_DNSData(domain=node.domain) ttl = random.randint(10, 300) Config.objects.set_config("default_dns_ttl", ttl) expected_mapping = { dnsdata1.dnsresource.name: HostnameRRsetMapping( node.system_id, {(ttl, dnsdata1.rrtype, dnsdata1.rrdata)}, node.node_type, ), dnsdata2.dnsresource.name: HostnameRRsetMapping( None, {(ttl, dnsdata2.rrtype, dnsdata2.rrdata)}, None ), } actual = get_hostname_dnsdata_mapping(node.domain) self.assertItemsEqual(expected_mapping.items(), actual.items())
def test_get_normal_user_only_owned_entries(self): user = factory.make_User() other_user = factory.make_User() handler = DomainHandler(user, {}, None) domain = factory.make_Domain() hostname1 = factory.make_name("node") factory.make_Node_with_Interface_on_Subnet(hostname=hostname1, domain=domain, owner=user) dnsrr1 = factory.make_DNSResource(domain=domain, name=hostname1) factory.make_DNSData(dnsresource=dnsrr1, ip_addresses=True) hostname2 = factory.make_name("node") factory.make_Node_with_Interface_on_Subnet(hostname=hostname2, domain=domain, owner=other_user) dnsrr2 = factory.make_DNSResource(domain=domain, name=hostname2) factory.make_DNSData(dnsresource=dnsrr2, ip_addresses=True) details = handler.get({"id": domain.id}) for entry in details['rrsets']: self.assertEqual(entry['user_id'], user.id)
def test__delete_dnsdata_fails_for_non_admin(self): user = factory.make_User() handler = DomainHandler(user, {}, None) domain = factory.make_Domain() dnsresource = factory.make_DNSResource(domain=domain) dnsdata = factory.make_DNSData(dnsresource) with ExpectedException(HandlerPermissionError): handler.delete_dnsdata( {"domain": domain.id, "dnsdata_id": dnsdata.id} ) dnsdata = reload_object(dnsdata) self.assertThat(dnsdata, Not(Is(None)))
def test_read_with_name(self): for _ in range(3): dnsdata = factory.make_DNSData() uri = get_dnsresourcerecords_uri() response = self.client.get(uri, {"name": [dnsdata.dnsresource.name]}) self.assertEqual(http.client.OK, response.status_code, response.content) expected_ids = [dnsdata.id] result_ids = [ data["id"] for data in json.loads( response.content.decode(settings.DEFAULT_CHARSET)) ] self.assertItemsEqual(expected_ids, result_ids)
def test_update(self): self.become_admin() dnsdata = factory.make_DNSData(rrtype="TXT", rrdata="1") new_data = factory.make_name("data") uri = get_dnsresourcerecord_uri(dnsdata) response = self.client.put(uri, {"rrdata": new_data}) self.assertEqual(http.client.OK, response.status_code, response.content) self.assertEqual( new_data, json.loads(response.content.decode( settings.DEFAULT_CHARSET))["rrdata"], )
def test_rejects_cname_with_other_data(self): name = factory.make_name('name') target = factory.make_name('target') domain = factory.make_Domain() rrtype = random.choice(['MX', 'NS', 'TXT']) dnsrr = factory.make_DNSData(name=name, domain=domain, no_ip_addresses=True, rrtype=rrtype).dnsresource dnsdata = DNSData(dnsresource=dnsrr, rrtype='CNAME', rrdata=target) with ExpectedException( ValidationError, re.escape("{'__all__': ['%s']}" % CNAME_AND_OTHER_MSG)): dnsdata.save()
def test_rejects_address_with_cname(self): name = factory.make_name('name') domain = factory.make_Domain() dnsdata = factory.make_DNSData( rrtype='CNAME', name=name, domain=domain) ipaddress = factory.make_StaticIPAddress() dnsrr = dnsdata.dnsresource dnsrr.ip_addresses.add(ipaddress) with ExpectedException( ValidationError, re.escape( "{'__all__': " "['Cannot add address: CNAME present.']")): dnsrr.save(force_update=True)
def test_rejects_cname_with_other_data(self): name = factory.make_name("name") target = factory.make_name("target") domain = factory.make_Domain() rrtype = random.choice(["MX", "NS", "TXT"]) dnsrr = factory.make_DNSData( name=name, domain=domain, no_ip_addresses=True, rrtype=rrtype ).dnsresource dnsdata = DNSData(dnsresource=dnsrr, rrtype="CNAME", rrdata=target) with ExpectedException( ValidationError, re.escape("{'__all__': ['%s']}" % CNAME_AND_OTHER_MSG), ): dnsdata.save()
def test__update_dnsdata(self): user = factory.make_admin() handler = DomainHandler(user, {}) domain = factory.make_Domain() dnsresource = factory.make_DNSResource(domain=domain) dnsdata = factory.make_DNSData( dnsresource, rrtype="TXT", rrdata="original") handler.update_dnsdata({ 'domain': domain.id, 'dnsresource_id': dnsresource.id, 'dnsdata_id': dnsdata.id, 'rrdata': 'updated', }) dnsdata = reload_object(dnsdata) self.assertThat(dnsdata.rrdata, Equals("updated"))
def test_creates_srv(self): service = factory.make_name(size=5) proto = factory.make_name(size=5) name = factory.make_name('name') target = factory.make_name('name') srv_name = '_%s._%s.%s' % (service, proto, name) data = "%d %d %d %s" % (random.randint( 0, 65535), random.randint(0, 65535), random.randint(1, 65535), target) dnsdata = factory.make_DNSData(rrtype='srv', rrdata=data, name=srv_name) from_db = DNSData.objects.get(dnsresource__name=srv_name) self.assertEqual((from_db.dnsresource.name, from_db.id, from_db.rrtype, from_db.rrdata), (srv_name, dnsdata.id, 'SRV', data))
def test_add_delegations_adds_nsrrset_and_glue(self): parent = factory.make_Domain() name = factory.make_name() child = factory.make_Domain(name="%s.%s" % (name, parent.name)) default_name = Domain.objects.get_default_domain().name dnsrr = factory.make_DNSResource(name='@', domain=child) nsname = factory.make_name() factory.make_DNSData(dnsresource=dnsrr, rrtype='NS', rrdata="%s.%s." % (nsname, child.name)) nsrr = factory.make_DNSResource(name=nsname, domain=child) other_name = factory.make_name() factory.make_DNSResource(name=other_name, domain=parent) factory.make_DNSData(dnsresource=dnsrr, rrtype='NS', rrdata="%s.%s." % (other_name, parent.name)) mappings = lazydict(get_hostname_dnsdata_mapping) mapping = mappings[parent] parent.add_delegations(mapping, default_name, [IPAddress("::1")], 30) expected_map = { name: HostnameRRsetMapping( rrset={ (30, 'NS', default_name), (30, 'NS', "%s.%s." % (nsname, child.name)), (30, 'NS', "%s.%s." % (other_name, parent.name)), }), } for sip in nsrr.ip_addresses.all(): if IPAddress(sip.ip).version == 6: expected_map[nsname] = HostnameRRsetMapping(rrset={(30, 'AAAA', sip.ip)}) else: expected_map[nsname] = HostnameRRsetMapping(rrset={(30, 'A', sip.ip)}) self.assertEqual(expected_map, mapping)
def test_read_with_type(self): for _ in range(3): dnsdata = factory.make_DNSData() rrtype = dnsdata.rrtype uri = get_dnsresourcerecords_uri() response = self.client.get(uri, {"rrtype": [rrtype]}) self.assertEqual(http.client.OK, response.status_code, response.content) expected_ids = [ data.id for data in DNSData.objects.filter(rrtype=rrtype) ] result_ids = [ data["id"] for data in json.loads( response.content.decode(settings.DEFAULT_CHARSET)) ] self.assertItemsEqual(expected_ids, result_ids)
def test__updates_dnsdata(self): dnsdata = factory.make_DNSData() (rrtype, rrdata) = factory.pick_rrset() new_ttl = random.randint(1, 1000) form = DNSDataForm(instance=dnsdata, data={ "rrtype": rrtype, "rrdata": rrdata, "ttl": new_ttl, }) self.assertTrue(form.is_valid(), form.errors) form.save() dnsdata = reload_object(dnsdata) self.assertEqual(rrtype, dnsdata.rrtype) self.assertEqual(rrdata, dnsdata.rrdata) self.assertEqual(new_ttl, dnsdata.ttl)
def test__update_dnsdata_fails_for_non_admin(self): user = factory.make_User() handler = DomainHandler(user, {}) domain = factory.make_Domain() dnsresource = factory.make_DNSResource(domain=domain) dnsdata = factory.make_DNSData( dnsresource, rrtype="TXT", rrdata="original") with ExpectedException(HandlerPermissionError): handler.update_dnsdata({ 'domain': domain.id, 'dnsresource_id': dnsresource.id, 'dnsdata_id': dnsdata.id, 'rrdata': 'updated', }) dnsdata = reload_object(dnsdata) self.assertThat(dnsdata.rrdata, Equals("original"))
def test_dnsdata_overrides_domain(self): # If DNSData has a ttl, we use that in preference to anything else. global_ttl = random.randint(100, 199) Config.objects.set_config('default_dns_ttl', global_ttl) subnet = factory.make_Subnet(cidr="10.0.0.0/23") domain = factory.make_Domain(ttl=random.randint(200, 299)) dnsrr = factory.make_DNSResource( no_ip_addresses=True, domain=domain, address_ttl=random.randint(400, 499)) dnsdata = factory.make_DNSData( dnsresource=dnsrr, ttl=random.randint(500, 599)) expected_forward = {dnsrr.name: HostnameRRsetMapping( None, {(dnsdata.ttl, dnsdata.rrtype, dnsdata.rrdata)})} zones = ZoneGenerator( domain, subnet, default_ttl=global_ttl, serial=random.randint(0, 65535)).as_list() self.assertEqual(expected_forward, zones[0]._other_mapping) self.assertEqual({}, zones[0]._mapping) self.assertEqual({}, zones[1]._mapping)
def test_renders_as_dictionary(self): domain = factory.make_Domain() name1 = factory.make_name(prefix='a') name2 = factory.make_name(prefix='b') factory.make_DNSData(name=name1, domain=domain, rrtype='MX') rrdata_list = domain.render_json_for_related_rrdata(as_dict=False) rrdata_dict = domain.render_json_for_related_rrdata(as_dict=True) self.assertThat(rrdata_dict[name1], Equals([rrdata_list[0]])) self.assertThat(rrdata_dict[name1], HasLength(1)) factory.make_DNSData(name=name1, domain=domain, rrtype='MX') factory.make_DNSData(name=name2, domain=domain, rrtype='NS') rrdata_dict = domain.render_json_for_related_rrdata(as_dict=True) self.assertThat(rrdata_dict[name1], HasLength(2)) self.assertThat(rrdata_dict[name2], HasLength(1))