コード例 #1
0
    def test_validate_router_config_existing_router(self):
        """
        If an existing router is already listening to the specified channel,
        then a config error should be raised
        """
        channel = yield self.create_channel(self.api.service,
                                            self.redis,
                                            properties={
                                                'type': 'telnet',
                                                'config': {
                                                    'twisted_endpoint':
                                                    'tcp:0',
                                                },
                                            })

        config = self.create_router_config(config={
            'test': 'pass',
            'channel': channel.id
        })
        router = Router(self.api, config)
        yield router.save()
        router.start(self.api.service)

        with self.assertRaises(InvalidRouterConfig) as e:
            yield FromAddressRouter.validate_router_config(
                self.api, {'channel': channel.id})

        self.assertEqual(
            e.exception.message,
            "Router {} is already routing channel {}".format(
                router.id, channel.id))
コード例 #2
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_remove_destination(self):
        """Removing a destination should remove it from the router store and
        the list of destinations on the router."""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)

        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        yield router.save()

        self.assertIn(destination.id, router.destinations)
        self.assertIn(
            destination.id,
            (yield self.api.router_store.get_router_destination_list(
                router.id))
        )

        yield destination.delete()

        self.assertNotIn(destination.id, router.destinations)
        self.assertNotIn(
            destination.id,
            (yield self.api.router_store.get_router_destination_list(
                router.id))
        )
コード例 #3
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_validate_config_invalid_worker_name(self):
        """If validate_config is given a config with an unknown worker name,
        an appropriate error should be raised."""
        config = self.create_router_config(type='invalid')
        router = Router(self.api, config)

        with self.assertRaises(InvalidRouterType):
            yield router.validate_config()
コード例 #4
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_delete_router_not_in_store(self):
        """Removing a non-existing router should not result in an error"""
        config = self.create_router_config()
        router = Router(self.api, config)
        self.assertEqual((yield self.api.router_store.get_router_list()), [])

        yield router.delete()
        self.assertEqual((yield self.api.router_store.get_router_list()), [])
コード例 #5
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_validate_config_invalid_worker_name(self):
        """If validate_config is given a config with an unknown worker name,
        an appropriate error should be raised."""
        config = self.create_router_config(type='invalid')
        router = Router(self.api, config)

        with self.assertRaises(InvalidRouterType):
            yield router.validate_config()
コード例 #6
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_delete_router_not_in_store(self):
        """Removing a non-existing router should not result in an error"""
        config = self.create_router_config()
        router = Router(self.api, config)
        self.assertEqual((yield self.api.router_store.get_router_list()), [])

        yield router.delete()
        self.assertEqual((yield self.api.router_store.get_router_list()), [])
コード例 #7
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_creating_uuid(self):
        """If a router isn't given an id, then it should generate one."""
        config = self.create_router_config()
        router = Router(self.api, config)
        self.assertFalse(router.router_config.get('id') is None)

        config = self.create_router_config(id='test-uuid')
        router = Router(self.api, config)
        self.assertEqual(router.router_config.get('id'), 'test-uuid')
コード例 #8
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_destination_status(self):
        """Getting the destination status should return the configuration of
        the destination"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        self.assertEqual(destination_config, (yield destination.status()))
コード例 #9
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_destination_status(self):
        """Getting the destination status should return the configuration of
        the destination"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        self.assertEqual(destination_config, (yield destination.status()))
コード例 #10
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_get_destination_list(self):
        """Getting the destination list of a router should return a list of
        destination ids for that router"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        router.start(self.api.service)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        self.assertEqual(router.get_destination_list(), [destination.id])
コード例 #11
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_delete_router(self):
        """Removes the router config from the store"""
        config = self.create_router_config()
        router = Router(self.api, config)
        yield router.save()
        self.assertEqual((yield self.api.router_store.get_router_list()),
                         [router.router_config['id']])

        yield router.delete()
        self.assertEqual((yield self.api.router_store.get_router_list()), [])
コード例 #12
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_add_destination(self):
        """add_destination should create and add the destination"""
        config = self.create_router_config()
        router = Router(self.api, config)

        self.assertEqual(router.destinations, {})

        destination = router.add_destination(self.create_destination_config())

        self.assertEqual(router.destinations, {destination.id: destination})
コード例 #13
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_add_destination(self):
        """add_destination should create and add the destination"""
        config = self.create_router_config()
        router = Router(self.api, config)

        self.assertEqual(router.destinations, {})

        destination = router.add_destination(self.create_destination_config())

        self.assertEqual(router.destinations, {destination.id: destination})
コード例 #14
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_delete_router(self):
        """Removes the router config from the store"""
        config = self.create_router_config()
        router = Router(self.api, config)
        yield router.save()
        self.assertEqual(
            (yield self.api.router_store.get_router_list()),
            [router.router_config['id']])

        yield router.delete()
        self.assertEqual((yield self.api.router_store.get_router_list()), [])
コード例 #15
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_stop(self):
        """stop should stop the router worker if it is running"""
        config = self.create_router_config()
        router = Router(self.api, config)
        router.start(self.service)

        self.assertIn(router.id, self.service.namedServices)

        yield router.stop()

        self.assertNotIn(router.id, self.service.namedServices)
コード例 #16
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_validate_config(self):
        """validate_config should run the validate config function on the
        router worker class"""
        config = self.create_router_config(config={'test': 'pass'})
        router = Router(self.api, config)
        yield router.validate_config()

        with self.assertRaises(InvalidRouterConfig):
            config = self.create_router_config(config={'test': 'fail'})
            router = Router(self.api, config)
            yield router.validate_config()
コード例 #17
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_start(self):
        """start should start the router worker with the correct config"""
        config = self.create_router_config()
        router = Router(self.api, config)
        router.start(self.service)

        router_worker = self.service.namedServices[router.id]
        self.assertEqual(router_worker.parent, self.service)
        router_worker_config = config['config']
        for k, v in router_worker_config.items():
            self.assertEqual(router_worker.config[k], v)
コード例 #18
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_start(self):
        """start should start the router worker with the correct config"""
        config = self.create_router_config()
        router = Router(self.api, config)
        router.start(self.service)

        router_worker = self.service.namedServices[router.id]
        self.assertEqual(router_worker.parent, self.service)
        router_worker_config = config['config']
        for k, v in router_worker_config.items():
            self.assertEqual(router_worker.config[k], v)
コード例 #19
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_stop(self):
        """stop should stop the router worker if it is running"""
        config = self.create_router_config()
        router = Router(self.api, config)
        router.start(self.service)

        self.assertIn(router.id, self.service.namedServices)

        yield router.stop()

        self.assertNotIn(router.id, self.service.namedServices)
コード例 #20
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_from_id(self):
        """from_id should be able to restore a router, given just the id"""
        config = self.create_router_config()
        router = Router(self.api, config)
        yield router.save()
        router.start(self.api.service)

        restored_router = yield Router.from_id(
            self.api, router.router_config['id'])

        self.assertEqual(router.router_config, restored_router.router_config)
        self.assertEqual(router.router_worker, restored_router.router_worker)
コード例 #21
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_validate_destination_config(self):
        """validate_destination_config should run the validate destination
        config on the router worker class"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)

        destination_config = {'target': 'valid'}
        yield router.validate_destination_config(destination_config)

        with self.assertRaises(InvalidRouterDestinationConfig):
            destination_config = {'target': 'invalid'}
            yield router.validate_destination_config(destination_config)
コード例 #22
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_destinations_are_passed_to_router_worker(self):
        """The destination configs should be passed to the router worker when
        the router is started."""
        config = self.create_router_config()
        router = Router(self.api, config)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        router.start(self.service)
        router_worker = self.service.namedServices[router.id]
        self.assertEqual(router_worker.config['destinations'],
                         [destination.destination_config])
コード例 #23
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_validate_destination_config(self):
        """validate_destination_config should run the validate destination
        config on the router worker class"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)

        destination_config = {'target': 'valid'}
        yield router.validate_destination_config(destination_config)

        with self.assertRaises(InvalidRouterDestinationConfig):
            destination_config = {'target': 'invalid'}
            yield router.validate_destination_config(destination_config)
コード例 #24
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_get_all(self):
        """get_all should return a list of all router ids"""
        self.assertEqual((yield Router.get_all(self.api.router_store)), [])

        config = self.create_router_config(id='test-uuid1')
        yield self.api.router_store.save_router(config)
        self.assertEqual((yield Router.get_all(self.api.router_store)),
                         ['test-uuid1'])

        config = self.create_router_config(id='test-uuid2')
        yield self.api.router_store.save_router(config)
        self.assertEqual((yield Router.get_all(self.api.router_store)),
                         ['test-uuid1', 'test-uuid2'])
コード例 #25
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_destinations_are_passed_to_router_worker(self):
        """The destination configs should be passed to the router worker when
        the router is started."""
        config = self.create_router_config()
        router = Router(self.api, config)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        router.start(self.service)
        router_worker = self.service.namedServices[router.id]
        self.assertEqual(
            router_worker.config['destinations'],
            [destination.destination_config])
コード例 #26
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_start_all(self):
        """start_all should start all of the stored routers"""
        config = self.create_router_config()
        router = Router(self.api, config)
        yield router.save()

        yield Router.start_all_routers(self.api)

        router_worker = self.service.namedServices[router.id]
        self.assertEqual(router_worker.parent, self.service)
        router_worker_config = config['config']
        for k, v in router_worker_config.items():
            self.assertEqual(router_worker.config[k], v)
コード例 #27
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_start_all(self):
        """start_all should start all of the stored routers"""
        config = self.create_router_config()
        router = Router(self.api, config)
        yield router.save()

        yield Router.start_all_routers(self.api)

        router_worker = self.service.namedServices[router.id]
        self.assertEqual(router_worker.parent, self.service)
        router_worker_config = config['config']
        for k, v in router_worker_config.items():
            self.assertEqual(router_worker.config[k], v)
コード例 #28
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_destination_save(self):
        """Saving a destination should save the destination's configuration to
        the router store"""
        router_store = self.api.router_store
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        self.assertEqual(
            (yield router_store.get_router_destination_list(router.id)), [])
        yield destination.save()
        self.assertEqual(
            (yield router_store.get_router_destination_list(router.id)),
            [destination.id])
コード例 #29
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_destination_save(self):
        """Saving a destination should save the destination's configuration to
        the router store"""
        router_store = self.api.router_store
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        self.assertEqual(
            (yield router_store.get_router_destination_list(router.id)), [])
        yield destination.save()
        self.assertEqual(
            (yield router_store.get_router_destination_list(router.id)),
            [destination.id])
コード例 #30
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_stop_already_stopped(self):
        """Calling stop on a non-running router should not raise any
        exceptions"""

        config = self.create_router_config()
        router = Router(self.api, config)
        router.start(self.service)

        self.assertIn(router.id, self.service.namedServices)

        yield router.stop()

        self.assertNotIn(router.id, self.service.namedServices)

        yield router.stop()
コード例 #31
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_get_all(self):
        """get_all should return a list of all router ids"""
        self.assertEqual(
            (yield Router.get_all(self.api.router_store)), [])

        config = self.create_router_config(id='test-uuid1')
        yield self.api.router_store.save_router(config)
        self.assertEqual(
            (yield Router.get_all(self.api.router_store)), ['test-uuid1'])

        config = self.create_router_config(id='test-uuid2')
        yield self.api.router_store.save_router(config)
        self.assertEqual(
            (yield Router.get_all(self.api.router_store)),
            ['test-uuid1', 'test-uuid2'])
コード例 #32
0
ファイル: api.py プロジェクト: todun/junebug
 def get_destination(self, request, router_id, destination_id):
     """Get the config and status of a destination"""
     router = yield Router.from_id(self, router_id)
     destination = router.get_destination(destination_id)
     returnValue(response(
         request, 'destination found', (yield destination.status())
     ))
コード例 #33
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_save(self):
        """save should save the configuration of the router and all the
        destinations into the router store"""
        config = self.create_router_config()
        router = Router(self.api, config)
        dest_config = self.create_destination_config()
        destination = router.add_destination(dest_config)

        self.assertEqual((yield self.api.router_store.get_router_list()), [])
        self.assertEqual(
            (yield self.api.router_store.get_router_destination_list(
                router.id)), [])
        yield router.save()
        self.assertEqual((yield self.api.router_store.get_router_list()),
                         [router.id])
        self.assertEqual(
            (yield self.api.router_store.get_router_destination_list(
                router.id)), [destination.id])
コード例 #34
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_save(self):
        """save should save the configuration of the router and all the
        destinations into the router store"""
        config = self.create_router_config()
        router = Router(self.api, config)
        dest_config = self.create_destination_config()
        destination = router.add_destination(dest_config)

        self.assertEqual((yield self.api.router_store.get_router_list()), [])
        self.assertEqual(
            (yield self.api.router_store.get_router_destination_list(
                router.id)), [])
        yield router.save()
        self.assertEqual(
            (yield self.api.router_store.get_router_list()), [router.id])
        self.assertEqual(
            (yield self.api.router_store.get_router_destination_list(
                router.id)), [destination.id])
コード例 #35
0
ファイル: api.py プロジェクト: todun/junebug
    def delete_router_destination(self, request, router_id, destination_id):
        """Delete and stop the router destination"""
        router = yield Router.from_id(self, router_id)
        destination = router.get_destination(destination_id)

        yield router.stop()
        yield destination.delete()
        router.start(self.service)

        returnValue(response(request, 'destination deleted', {}))
コード例 #36
0
ファイル: api.py プロジェクト: todun/junebug
    def update_router_config(self, request, body, router_id):
        """Update the router config with the one specified"""
        router = yield Router.from_id(self, router_id)

        router.router_config.update(body)
        yield router.validate_config()

        # Stop and start the router for the worker to get the new config
        yield router.stop()
        router.start(self.service)
        yield router.save()
        returnValue(response(
            request, 'router updated', (yield router.status())))
コード例 #37
0
ファイル: api.py プロジェクト: todun/junebug
 def create_router(self, request, body):
     """Create a new router"""
     router = Router(self, body)
     yield router.validate_config()
     router.start(self.service)
     yield router.save()
     returnValue(response(
         request,
         'router created',
         (yield router.status()),
         code=http.CREATED
     ))
コード例 #38
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_remove_destination(self):
        """Removing a destination should remove it from the router store and
        the list of destinations on the router."""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)

        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        yield router.save()

        self.assertIn(destination.id, router.destinations)
        self.assertIn(destination.id,
                      (yield self.api.router_store.get_router_destination_list(
                          router.id)))

        yield destination.delete()

        self.assertNotIn(destination.id, router.destinations)
        self.assertNotIn(
            destination.id,
            (yield self.api.router_store.get_router_destination_list(
                router.id)))
コード例 #39
0
ファイル: api.py プロジェクト: todun/junebug
    def create_router_destination(self, request, body, router_id):
        """Create a new destination for the router"""
        router = yield Router.from_id(self, router_id)
        yield router.validate_destination_config(body['config'])

        destination = router.add_destination(body)
        yield router.stop()
        router.start(self.service)
        yield destination.save()

        returnValue(response(
            request, 'destination created', (yield destination.status()),
            code=http.CREATED
        ))
コード例 #40
0
ファイル: api.py プロジェクト: todun/junebug
    def replace_router_config(self, request, body, router_id):
        """Replace the router config with the one specified"""
        router = yield Router.from_id(self, router_id)

        for field in ['type', 'label', 'config', 'metadata']:
            router.router_config.pop(field, None)
        router.router_config.update(body)
        yield router.validate_config()

        # Stop and start the router for the worker to get the new config
        yield router.stop()
        router.start(self.service)
        yield router.save()
        returnValue(response(
            request, 'router updated', (yield router.status())))
コード例 #41
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_get_destination_list(self):
        """Getting the destination list of a router should return a list of
        destination ids for that router"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        router.start(self.api.service)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)

        self.assertEqual(router.get_destination_list(), [destination.id])
コード例 #42
0
ファイル: api.py プロジェクト: todun/junebug
    def update_router_destination(
            self, request, body, router_id, destination_id):
        """Update the config of a router destination"""
        router = yield Router.from_id(self, router_id)
        if 'config' in body:
            yield router.validate_destination_config(body['config'])

        destination = router.get_destination(destination_id)
        destination.destination_config.update(body)

        # Stop and start the router for the worker to get the new config
        yield router.stop()
        router.start(self.service)
        yield destination.save()
        returnValue(response(
            request, 'destination updated', (yield destination.status())))
コード例 #43
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_validate_config(self):
        """validate_config should run the validate config function on the
        router worker class"""
        config = self.create_router_config(config={'test': 'pass'})
        router = Router(self.api, config)
        yield router.validate_config()

        with self.assertRaises(InvalidRouterConfig):
            config = self.create_router_config(config={'test': 'fail'})
            router = Router(self.api, config)
            yield router.validate_config()
コード例 #44
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_from_id(self):
        """from_id should be able to restore a router, given just the id"""
        config = self.create_router_config()
        router = Router(self.api, config)
        yield router.save()
        router.start(self.api.service)

        restored_router = yield Router.from_id(self.api,
                                               router.router_config['id'])

        self.assertEqual(router.router_config, restored_router.router_config)
        self.assertEqual(router.router_worker, restored_router.router_worker)
コード例 #45
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_destinations_restored_on_router_from_id(self):
        """Creating a router object from id should also restore the
        destinations for that router"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        router.start(self.api.service)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)
        yield router.save()

        restored_router = yield Router.from_id(self.api, router.id)
        self.assertEqual(router.destinations.keys(),
                         restored_router.destinations.keys())
        self.assertEqual(
            router.destinations[destination.id].destination_config,
            restored_router.destinations[destination.id].destination_config)
コード例 #46
0
ファイル: test_router.py プロジェクト: todun/junebug
    def test_stop_already_stopped(self):
        """Calling stop on a non-running router should not raise any
        exceptions"""

        config = self.create_router_config()
        router = Router(self.api, config)
        router.start(self.service)

        self.assertIn(router.id, self.service.namedServices)

        yield router.stop()

        self.assertNotIn(router.id, self.service.namedServices)

        yield router.stop()
コード例 #47
0
ファイル: test_router.py プロジェクト: praekelt/junebug
    def test_destinations_restored_on_router_from_id(self):
        """Creating a router object from id should also restore the
        destinations for that router"""
        router_config = self.create_router_config()
        router = Router(self.api, router_config)
        router.start(self.api.service)
        destination_config = self.create_destination_config()
        destination = router.add_destination(destination_config)
        yield router.save()

        restored_router = yield Router.from_id(self.api, router.id)
        self.assertEqual(
            router.destinations.keys(), restored_router.destinations.keys())
        self.assertEqual(
            router.destinations[destination.id].destination_config,
            restored_router.destinations[destination.id].destination_config)
コード例 #48
0
ファイル: api.py プロジェクト: todun/junebug
    def setup(self, redis=None, message_sender=None):
        if redis is None:
            redis = yield TxRedisManager.from_config(self.redis_config)

        if message_sender is None:
            message_sender = MessageSender(
                'amqp-spec-0-8.xml', self.amqp_config)

        self.redis = redis
        self.message_sender = message_sender
        self.message_sender.setServiceParent(self.service)

        self.inbounds = InboundMessageStore(
            self.redis, self.config.inbound_message_ttl)

        self.outbounds = OutboundMessageStore(
            self.redis, self.config.outbound_message_ttl)

        self.message_rate = MessageRateStore(self.redis)

        self.router_store = RouterStore(self.redis)

        self.plugins = []
        for plugin_config in self.config.plugins:
            cls = load_class_by_string(plugin_config['type'])
            plugin = cls()
            yield plugin.start_plugin(plugin_config, self.config)
            self.plugins.append(plugin)

        yield Channel.start_all_channels(
            self.redis, self.config, self.service, self.plugins)

        yield Router.start_all_routers(self)

        if self.config.rabbitmq_management_interface:
            self.rabbitmq_management_client = RabbitmqManagementClient(
                self.config.rabbitmq_management_interface,
                self.amqp_config['username'],
                self.amqp_config['password'])
コード例 #49
0
ファイル: api.py プロジェクト: todun/junebug
 def get_router_destination_list(self, request, router_id):
     """Get the list of destinations for a router"""
     d = Router.from_id(self, router_id)
     d.addCallback(lambda router: router.get_destination_list())
     d.addCallback(partial(response, request, 'destinations retrieved'))
     return d
コード例 #50
0
ファイル: api.py プロジェクト: praekelt/junebug
 def delete_router(self, request, router_id):
     router = yield Router.from_id(self, router_id)
     yield router.stop()
     yield router.delete()
     returnValue(response(request, 'router deleted', {}))
コード例 #51
0
ファイル: api.py プロジェクト: praekelt/junebug
 def get_router(self, request, router_id):
     """Get the configuration details and status of a specific router"""
     d = Router.from_id(self, router_id)
     d.addCallback(lambda router: router.status())
     d.addCallback(partial(response, request, 'router found'))
     return d