Exemplo n.º 1
0
    def test_retry_behavior(self):
        provider = CloudflareProvider('test', token='token 123',
                                      email='email 234', retry_period=0)
        result = {
            "success": True,
            "errors": [],
            "messages": [],
            "result": [],
            "result_info": {
                "count": 1,
                "per_page": 50
            }
        }
        zone = Zone('unit.tests.', [])
        provider._request = Mock()

        # No retry required, just calls and is returned
        provider._zones = None
        provider._request.reset_mock()
        provider._request.side_effect = [result]
        self.assertEquals([], provider.zone_records(zone))
        provider._request.assert_has_calls([call('GET', '/zones',
                                           params={'page': 1})])

        # One retry required
        provider._zones = None
        provider._request.reset_mock()
        provider._request.side_effect = [
            CloudflareRateLimitError('{}'),
            result
        ]
        self.assertEquals([], provider.zone_records(zone))
        provider._request.assert_has_calls([call('GET', '/zones',
                                           params={'page': 1})])

        # Two retries required
        provider._zones = None
        provider._request.reset_mock()
        provider._request.side_effect = [
            CloudflareRateLimitError('{}'),
            CloudflareRateLimitError('{}'),
            result
        ]
        self.assertEquals([], provider.zone_records(zone))
        provider._request.assert_has_calls([call('GET', '/zones',
                                           params={'page': 1})])

        # # Exhaust our retries
        provider._zones = None
        provider._request.reset_mock()
        provider._request.side_effect = [
            CloudflareRateLimitError({"errors": [{"message": "first"}]}),
            CloudflareRateLimitError({"errors": [{"message": "boo"}]}),
            CloudflareRateLimitError({"errors": [{"message": "boo"}]}),
            CloudflareRateLimitError({"errors": [{"message": "boo"}]}),
            CloudflareRateLimitError({"errors": [{"message": "last"}]}),
        ]
        with self.assertRaises(CloudflareRateLimitError) as ctx:
            provider.zone_records(zone)
            self.assertEquals('last', text_type(ctx.exception))
    def test_populate(self):
        provider = CloudflareProvider('test', 'email', 'token')

        # Bad requests
        with requests_mock() as mock:
            mock.get(ANY,
                     status_code=400,
                     text='{"success":false,"errors":[{"code":1101,'
                     '"message":"request was invalid"}],'
                     '"messages":[],"result":null}')

            with self.assertRaises(Exception) as ctx:
                zone = Zone('unit.tests.', [])
                provider.populate(zone)

            self.assertEquals('CloudflareError', type(ctx.exception).__name__)
            self.assertEquals('request was invalid', ctx.exception.message)

        # Bad auth
        with requests_mock() as mock:
            mock.get(ANY,
                     status_code=403,
                     text='{"success":false,"errors":[{"code":9103,'
                     '"message":"Unknown X-Auth-Key or X-Auth-Email"}],'
                     '"messages":[],"result":null}')

            with self.assertRaises(Exception) as ctx:
                zone = Zone('unit.tests.', [])
                provider.populate(zone)
            self.assertEquals('CloudflareAuthenticationError',
                              type(ctx.exception).__name__)
            self.assertEquals('Unknown X-Auth-Key or X-Auth-Email',
                              ctx.exception.message)

        # Bad auth, unknown resp
        with requests_mock() as mock:
            mock.get(ANY, status_code=403, text='{}')

            with self.assertRaises(Exception) as ctx:
                zone = Zone('unit.tests.', [])
                provider.populate(zone)
            self.assertEquals('CloudflareAuthenticationError',
                              type(ctx.exception).__name__)
            self.assertEquals('Cloudflare error', ctx.exception.message)

        # General error
        with requests_mock() as mock:
            mock.get(ANY, status_code=502, text='Things caught fire')

            with self.assertRaises(HTTPError) as ctx:
                zone = Zone('unit.tests.', [])
                provider.populate(zone)
            self.assertEquals(502, ctx.exception.response.status_code)

        # Non-existant zone doesn't populate anything
        with requests_mock() as mock:
            mock.get(ANY, status_code=200, json=self.empty)

            zone = Zone('unit.tests.', [])
            provider.populate(zone)
            self.assertEquals(set(), zone.records)

        # re-populating the same non-existant zone uses cache and makes no
        # calls
        again = Zone('unit.tests.', [])
        provider.populate(again)
        self.assertEquals(set(), again.records)

        # bust zone cache
        provider._zones = None

        # existing zone with data
        with requests_mock() as mock:
            base = 'https://api.cloudflare.com/client/v4/zones'

            # zones
            with open('tests/fixtures/cloudflare-zones-page-1.json') as fh:
                mock.get('{}?page=1'.format(base),
                         status_code=200,
                         text=fh.read())
            with open('tests/fixtures/cloudflare-zones-page-2.json') as fh:
                mock.get('{}?page=2'.format(base),
                         status_code=200,
                         text=fh.read())
            mock.get('{}?page=3'.format(base),
                     status_code=200,
                     json={
                         'result': [],
                         'result_info': {
                             'count': 0,
                             'per_page': 0
                         }
                     })

            # records
            base = '{}/234234243423aaabb334342aaa343435/dns_records' \
                .format(base)
            with open('tests/fixtures/cloudflare-dns_records-'
                      'page-1.json') as fh:
                mock.get('{}?page=1'.format(base),
                         status_code=200,
                         text=fh.read())
            with open('tests/fixtures/cloudflare-dns_records-'
                      'page-2.json') as fh:
                mock.get('{}?page=2'.format(base),
                         status_code=200,
                         text=fh.read())

            zone = Zone('unit.tests.', [])
            provider.populate(zone)
            self.assertEquals(12, len(zone.records))

            changes = self.expected.changes(zone, provider)

            self.assertEquals(0, len(changes))

        # re-populating the same zone/records comes out of cache, no calls
        again = Zone('unit.tests.', [])
        provider.populate(again)
        self.assertEquals(12, len(again.records))