Esempio n. 1
0
 def test_subname_validity(self):
     for subname in ['aEroport', 'AEROPORT', 'aéroport']:
         with self.assertRaises(ValidationError):
             RRset(domain=self.my_domain, subname=subname, ttl=60,
                   type='A').save()
     RRset(domain=self.my_domain, subname='aeroport', ttl=60,
           type='A').save()
Esempio n. 2
0
        def pdns_do(self):
            data = {
                'rrsets':
                    [
                        {
                            'name': RRset.construct_name(subname, self._domain_name),
                            'type': type_,
                            'ttl': 1,  # some meaningless integer required by pdns's syntax
                            'changetype': 'REPLACE',  # don't use "DELETE" due to desec-stack#220, PowerDNS/pdns#7501
                            'records': []
                        }
                        for type_, subname in self._deletions
                    ] + [
                        {
                            'name': RRset.construct_name(subname, self._domain_name),
                            'type': type_,
                            'ttl': RRset.objects.values_list('ttl', flat=True).get(domain__name=self._domain_name,
                                                                                   type=type_, subname=subname),
                            'changetype': 'REPLACE',
                            'records': [
                                {'content': rr.content, 'disabled': False}
                                for rr in RR.objects.filter(
                                    rrset__domain__name=self._domain_name,
                                    rrset__type=type_,
                                    rrset__subname=subname)
                            ]
                        }
                        for type_, subname in (self._additions | self._modifications) - self._deletions
                    ]
            }

            if data['rrsets']:
                _pdns_patch(NSLORD, '/zones/' + self.domain_pdns_id, data)
Esempio n. 3
0
 def create_rr_set(cls, domain, records, **kwargs):
     if isinstance(domain, str):
         domain = Domain.objects.get(name=domain)
         domain.save()
     rr_set = RRset(domain=domain, **kwargs)
     rr_set.save()
     for r in records:
         RR(content=r, rrset=rr_set).save()
     return rr_set
Esempio n. 4
0
        def api_do(self):
            rr_set = RRset(
                domain=Domain.objects.get(name=self.domain_name),
                type='NS', subname='',
                ttl=settings.DEFAULT_NS_TTL,
            )
            rr_set.save()

            rrs = [RR(rrset=rr_set, content=ns) for ns in settings.DEFAULT_NS]
            RR.objects.bulk_create(rrs)  # One INSERT
Esempio n. 5
0
    def update(self, instance: RRset, validated_data):
        rrs_data = validated_data.pop('records', None)
        if rrs_data is not None:
            self._set_all_record_contents(instance, rrs_data)

        ttl = validated_data.pop('ttl', None)
        if ttl and instance.ttl != ttl:
            instance.ttl = ttl
            instance.save()

        return instance
Esempio n. 6
0
    def _set_all_record_contents(rrset: models.RRset, rrs):
        """
        Updates this RR set's resource records, discarding any old values.

        :param rrset: the RRset at which we overwrite all RRs
        :param rrs: list of RR representations
        """
        record_contents = [rr['content'] for rr in rrs]
        try:
            rrset.save_records(record_contents)
        except django.core.exceptions.ValidationError as e:
            raise serializers.ValidationError(e.messages, code='record-content')
 def _create_rr_sets(cls, data, domain):
     rr_sets = []
     rrs = {}
     for (type_, subname, ttl), rr_contents in data.items():
         rr_set = RRset(domain=domain, subname=subname, type=type_, ttl=ttl)
         rr_sets.append(rr_set)
         rrs[(type_, subname)] = this_rrs = []
         rr_set.save()
         for content in rr_contents:
             rr = RR(content=content, rrset=rr_set)
             this_rrs.append(rr)
             rr.save()
     return rr_sets, rrs
Esempio n. 8
0
    def update(self, instance: models.RRset, validated_data):
        rrs_data = validated_data.pop('records', None)
        if rrs_data is not None:
            self._set_all_record_contents(instance, rrs_data)

        ttl = validated_data.pop('ttl', None)
        if ttl and instance.ttl != ttl:
            instance.ttl = ttl
            instance.save()  # also updates instance.touched
        else:
            # Update instance.touched without triggering post-save signal (no pdns action required)
            models.RRset.objects.filter(pk=instance.pk).update(touched=timezone.now())

        return instance
Esempio n. 9
0
 def _sync_domain(domain):
     domain.rrset_set.all().delete()
     rrsets = []
     rrs = []
     for rrset_data in pdns.get_rrset_datas(domain):
         if rrset_data['type'] in RR_SET_TYPES_AUTOMATIC:
             continue
         records = rrset_data.pop('records')
         rrset = RRset(**rrset_data)
         rrsets.append(rrset)
         rrs.extend([RR(rrset=rrset, content=record) for record in records])
     RRset.objects.bulk_create(rrsets)
     RR.objects.bulk_create(rrs)
Esempio n. 10
0
    def test_retrieve_my_rr_sets_pagination(self):
        def convert_links(links):
            mapping = {}
            for link in links.split(', '):
                _url, label = link.split('; ')
                label = re.search('rel="(.*)"', label).group(1)
                _url = _url[1:-1]
                assert label not in mapping
                mapping[label] = _url
            return mapping

        def assertPaginationResponse(response, expected_length, expected_directional_links=[]):
            self.assertStatus(response, status.HTTP_200_OK)
            self.assertEqual(len(response.data), expected_length)

            _links = convert_links(response['Link'])
            self.assertEqual(len(_links), len(expected_directional_links) + 1)  # directional links, plus "first"
            self.assertTrue(_links['first'].endswith('/?cursor='))
            for directional_link in expected_directional_links:
                self.assertEqual(_links['first'].find('/?cursor='), _links[directional_link].find('/?cursor='))
                self.assertTrue(len(_links[directional_link]) > len(_links['first']))

        # Prepare extra records so that we get three pages (total: n + 1)
        n = int(settings.REST_FRAMEWORK['PAGE_SIZE'] * 2.5)
        RRset.objects.bulk_create(
            [RRset(domain=self.my_domain, subname=str(i), ttl=123, type='A') for i in range(n)]
        )

        # No pagination
        response = self.client.get_rr_sets(self.my_domain.name)
        self.assertStatus(response, status.HTTP_400_BAD_REQUEST)
        self.assertEqual(response.data['detail'],
                         f'Pagination required. You can query up to {settings.REST_FRAMEWORK["PAGE_SIZE"]} items at a time ({n+1} total). '
                         'Please use the `first` page link (see Link header).')
        links = convert_links(response['Link'])
        self.assertEqual(len(links), 1)
        self.assertTrue(links['first'].endswith('/?cursor='))

        # First page
        url = links['first']
        response = self.client.get(url)
        assertPaginationResponse(response, settings.REST_FRAMEWORK['PAGE_SIZE'], ['next'])

        # Next
        url = convert_links(response['Link'])['next']
        response = self.client.get(url)
        assertPaginationResponse(response, settings.REST_FRAMEWORK['PAGE_SIZE'], ['next', 'prev'])
        data_next = response.data.copy()

        # Next-next (last) page
        url = convert_links(response['Link'])['next']
        response = self.client.get(url)
        assertPaginationResponse(response, n/5 + 1, ['prev'])

        # Prev
        url = convert_links(response['Link'])['prev']
        response = self.client.get(url)
        assertPaginationResponse(response, settings.REST_FRAMEWORK['PAGE_SIZE'], ['next', 'prev'])

        # Make sure that one step forward equals two steps forward and one step back
        self.assertEqual(response.data, data_next)
 def test_rrset_does_not_exist_exception(self):
     tracker = PDNSChangeTracker()
     tracker.__enter__()
     tracker._rr_set_updated(RRset(domain=self.empty_domain, subname='', type='A'))
     with self.assertRaises(ValueError):
         tracker.__exit__(None, None, None)