示例#1
0
    def test_sync(self, execute_mock):
        provider = DynProvider('test', 'cust', 'user', 'pass')

        # Test Zone create
        execute_mock.side_effect = [
            # No such zone, during populate
            DynectGetError('foo'),
            # No such zone, during sync
            DynectGetError('foo'),
            # get empty Zone
            {
                'data': {}
            },
            # get zone we can modify & delete with
            {
                'data': {
                    # A top-level to delete
                    'a_records': [{
                        'fqdn': 'www.unit.tests',
                        'rdata': {
                            'address': '1.2.3.4'
                        },
                        'record_id': 1,
                        'record_type': 'A',
                        'ttl': 300,
                        'zone': 'unit.tests',
                    }],
                    # A node to delete
                    'alias_records': [{
                        'fqdn': 'unit.tests',
                        'rdata': {
                            'alias': 'www.unit.tests.'
                        },
                        'record_id': 2,
                        'record_type': 'ALIAS',
                        'ttl': 300,
                        'zone': 'unit.tests',
                    }],
                }
            }
        ]

        # No existing records, create all
        with patch('dyn.tm.zones.Zone.add_record') as add_mock:
            with patch('dyn.tm.zones.Zone._update') as update_mock:
                plan = provider.plan(self.expected)
                update_mock.assert_not_called()
                provider.apply(plan)
                update_mock.assert_called()
            add_mock.assert_called()
            # Once for each dyn record
            self.assertEquals(2, len(add_mock.call_args_list))
        execute_mock.assert_has_calls([
            call('/Zone/unit.tests/', 'GET', {}),
            call('/Zone/unit.tests/', 'GET', {})
        ])
        self.assertEquals(2, len(plan.changes))
示例#2
0
    def _process_response(self, response, method, final=False):
        """Process an API response for failure, incomplete, or success and
        throw any appropriate errors

        :param response: the JSON response from the request being processed
        :param method: the HTTP method
        :param final: boolean flag representing whether or not to continue
            polling
        """
        status = response['status']
        self.logger.debug(status)
        if status == 'success':
            return response
        elif status == 'failure':
            msgs = response['msgs']
            if method == 'POST' and 'login' in msgs[0]['INFO']:
                raise DynectAuthError(response['msgs'])
            if method == 'POST':
                raise DynectCreateError(response['msgs'])
            elif method == 'GET':
                raise DynectGetError(response['msgs'])
            elif method == 'PUT':
                raise DynectUpdateError(response['msgs'])
            else:
                raise DynectDeleteError(response['msgs'])
        else:  # Status was incomplete
            job_id = response['job_id']
            if not final:
                response = self.wait_for_job_to_complete(job_id)
                return self._process_response(response, method, True)
            else:
                raise DynectQueryTimeout({})
示例#3
0
    def test_populate_non_existent(self, execute_mock):
        provider = DynProvider('test', 'cust', 'user', 'pass')

        # Test Zone create
        execute_mock.side_effect = [
            DynectGetError('foo'),
        ]
        got = Zone('unit.tests.', [])
        provider.populate(got)
        execute_mock.assert_has_calls([
            call('/Zone/unit.tests/', 'GET', {}),
        ])
        self.assertEquals(set(), got.records)
示例#4
0
    def test_sync(self, execute_mock):
        provider = DynProvider('test', 'cust', 'user', 'pass')

        # Test Zone create
        execute_mock.side_effect = [
            # No such zone, during populate
            DynectGetError('foo'),
            # No such zone, during sync
            DynectGetError('foo'),
            # get empty Zone
            {
                'data': {}
            },
            # get zone we can modify & delete with
            {
                'data': {
                    # A top-level to delete
                    'a_records': [{
                        'fqdn': 'unit.tests',
                        'rdata': {
                            'address': '1.2.3.4'
                        },
                        'record_id': 1,
                        'record_type': 'A',
                        'ttl': 30,
                        'zone': 'unit.tests',
                    }, {
                        'fqdn': 'a.unit.tests',
                        'rdata': {
                            'address': '2.3.4.5'
                        },
                        'record_id': 2,
                        'record_type': 'A',
                        'ttl': 30,
                        'zone': 'unit.tests',
                    }],
                    # A node to delete
                    'cname_records': [{
                        'fqdn': 'cname.unit.tests',
                        'rdata': {
                            'cname': 'unit.tests.'
                        },
                        'record_id': 3,
                        'record_type': 'CNAME',
                        'ttl': 30,
                        'zone': 'unit.tests',
                    }],
                    # A record to leave alone
                    'ptr_records': [{
                        'fqdn': 'ptr.unit.tests',
                        'rdata': {
                            'ptrdname': 'xx.unit.tests.'
                        },
                        'record_id': 4,
                        'record_type': 'PTR',
                        'ttl': 30,
                        'zone': 'unit.tests',
                    }],
                    # A record to modify
                    'srv_records': [{
                        'fqdn': '_srv._tcp.unit.tests',
                        'rdata': {
                            'port': 10,
                            'priority': 11,
                            'target': 'foo-1.unit.tests.',
                            'weight': 12
                        },
                        'record_id': 5,
                        'record_type': 'SRV',
                        'ttl': 30,
                        'zone': 'unit.tests',
                    }, {
                        'fqdn': '_srv._tcp.unit.tests',
                        'rdata': {
                            'port': 20,
                            'priority': 21,
                            'target': 'foo-2.unit.tests.',
                            'weight': 22
                        },
                        'record_id': 6,
                        'record_type': 'SRV',
                        'ttl': 30,
                        'zone': 'unit.tests',
                    }],
                }
            }
        ]

        # No existing records, create all
        with patch('dyn.tm.zones.Zone.add_record') as add_mock:
            with patch('dyn.tm.zones.Zone._update') as update_mock:
                plan = provider.plan(self.expected)
                update_mock.assert_not_called()
                provider.apply(plan)
                update_mock.assert_called()
            add_mock.assert_called()
            # Once for each dyn record (8 Records, 2 of which have dual values)
            self.assertEquals(15, len(add_mock.call_args_list))
        execute_mock.assert_has_calls([
            call('/Zone/unit.tests/', 'GET', {}),
            call('/Zone/unit.tests/', 'GET', {})
        ])
        self.assertEquals(10, len(plan.changes))

        execute_mock.reset_mock()

        # Delete one and modify another
        new = Zone('unit.tests.', [])
        for name, data in (('a', {
                'type': 'A',
                'ttl': 30,
                'value': '2.3.4.5'
        }), ('ptr', {
                'type': 'PTR',
                'ttl': 30,
                'value': 'xx.unit.tests.'
        }), ('_srv._tcp', {
                'type':
                'SRV',
                'ttl':
                30,
                'values': [{
                    'priority': 31,
                    'weight': 12,
                    'port': 10,
                    'target': 'foo-1.unit.tests.'
                }, {
                    'priority': 21,
                    'weight': 22,
                    'port': 20,
                    'target': 'foo-2.unit.tests.'
                }]
        })):
            new.add_record(Record.new(new, name, data))

        with patch('dyn.tm.zones.Zone.add_record') as add_mock:
            with patch('dyn.tm.records.DNSRecord.delete') as delete_mock:
                with patch('dyn.tm.zones.Zone._update') as update_mock:
                    plan = provider.plan(new)
                    provider.apply(plan)
                    update_mock.assert_called()
                # we expect 4 deletes, 2 from actual deletes and 2 from
                # updates which delete and recreate
                self.assertEquals(4, len(delete_mock.call_args_list))
            # the 2 (re)creates
            self.assertEquals(2, len(add_mock.call_args_list))
        execute_mock.assert_has_calls([
            call('/AllRecord/unit.tests/unit.tests./', 'GET', {'detail': 'Y'})
        ])
        self.assertEquals(3, len(plan.changes))