Example #1
0
def main():
    parser = argparse.ArgumentParser(description='Run a hpfeeds broker')
    parser.add_argument('--bind', default=None, action='store')
    parser.add_argument('--exporter', default='', action='store')
    parser.add_argument('--name', default='hpfeeds', action='store')
    parser.add_argument('--debug', default=False, action='store_true')
    parser.add_argument('--auth', default=None, action='append')
    parser.add_argument('--tlscert', default=None, action='store')
    parser.add_argument('--tlskey', default=None, action='store')
    parser.add_argument('-e', '--endpoint', default=None, action='append')
    args = parser.parse_args()

    if (args.tlscert and not args.tlskey) or (args.tlskey
                                              and not args.tlscert):
        parser.error('Must specify --tlskey AND --tlscert')
        return

    logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO, )

    auth = multi.Authenticator()
    auths = args.auth if args.auth else ['sqlite']
    for a in auths:
        try:
            auth.add(get_authenticator(a))
        except ServerException as e:
            print(str(e))
            sys.exit(1)

    broker = Server(
        auth=auth,
        exporter=args.exporter,
        name=args.name,
    )

    if args.bind or not args.endpoint:
        bind = args.bind or '0.0.0.0:20000'
        broker.add_endpoint_legacy(bind,
                                   tlscert=args.tlscert,
                                   tlskey=args.tlskey)

    if args.endpoint:
        for endpoint in args.endpoint:
            broker.add_endpoint_str(endpoint)

    return aiorun.run(broker.serve_forever())
Example #2
0
class TestBrokerIntegration(unittest.TestCase):

    log = logging.getLogger('hpfeeds.test_broker_connection')

    def setUp(self):
        authenticator = Authenticator({
            'test': {
                'secret': 'secret',
                'subchans': ['test-chan'],
                'pubchans': ['test-chan'],
                'owner': 'some-owner',
            }
        })

        self.server = Server(authenticator)
        self.server.add_endpoint_str(
            "tls:interface=127.0.0.1:port=0:cert=hpfeeds/tests/testcert.crt:key=hpfeeds/tests/testcert.key"
        )

    def test_subscribe_and_publish(self):
        prometheus.reset()

        async def inner():
            self.log.debug('Starting server')
            server_future = asyncio.ensure_future(self.server.serve_forever())
            await self.server.when_started

            self.port = self.server.endpoints[0]['port']

            import ssl
            ssl_context = ssl.create_default_context(
                ssl.Purpose.SERVER_AUTH, cafile='hpfeeds/tests/testcert.crt')
            ssl_context.check_hostname = False

            self.log.debug('Creating client service')
            client = ClientSession('127.0.0.1',
                                   self.port,
                                   'test',
                                   'secret',
                                   ssl=ssl_context)
            client.subscribe('test-chan')

            # Wait till client connected
            await client.when_connected

            assert prometheus.REGISTRY.get_sample_value(
                'hpfeeds_broker_client_connections') == 1
            assert prometheus.REGISTRY.get_sample_value(
                'hpfeeds_broker_connection_made') == 1

            self.log.debug('Publishing test message')
            client.publish('test-chan', b'test message')

            self.log.debug('Waiting for read()')
            assert ('test', 'test-chan',
                    b'test message') == await client.read()

            # We would test this after call to subscribe, but need to wait until sure server has processed command
            assert prometheus.REGISTRY.get_sample_value(
                'hpfeeds_broker_subscriptions', {
                    'ident': 'test',
                    'chan': 'test-chan'
                }) == 1

            # This will only have incremented when server has processed auth message
            # Test can only reliably assert this is the case after reading a message
            assert prometheus.REGISTRY.get_sample_value(
                'hpfeeds_broker_connection_ready', {'ident': 'test'}) == 1

            self.log.debug('Stopping client')
            await client.close()

            assert prometheus.REGISTRY.get_sample_value(
                'hpfeeds_broker_connection_send_buffer_fill',
                {'ident': 'test'}) == 12
            assert prometheus.REGISTRY.get_sample_value(
                'hpfeeds_broker_connection_send_buffer_drain',
                {'ident': 'test'}) == 32

            self.log.debug('Stopping server')
            server_future.cancel()
            await server_future

        asyncio.get_event_loop().run_until_complete(inner())
        assert len(self.server.connections) == 0, 'Connection left dangling'
        assert prometheus.REGISTRY.get_sample_value(
            'hpfeeds_broker_client_connections') == 0
        assert prometheus.REGISTRY.get_sample_value(
            'hpfeeds_broker_connection_lost', {'ident': 'test'}) == 1

        # Closing should auto unsubscribe
        assert prometheus.REGISTRY.get_sample_value(
            'hpfeeds_broker_subscriptions', {
                'ident': 'test',
                'chan': 'test-chan'
            }) == 0