Beispiel #1
0
 def test_with_user_specified_exceptions(self, container):
     something_expected = get_extension(container,
                                        Consumer,
                                        method_name="something_expected")
     assert issubclass(self.UserException,
                       something_expected.expected_exceptions)
     assert issubclass(Backoff, something_expected.expected_exceptions)
Beispiel #2
0
 def test_with_user_specified_exceptions_including_backoff(self, container):
     backoff_expected = get_extension(container,
                                      Consumer,
                                      method_name="backoff_expected")
     assert issubclass(self.UserException,
                       backoff_expected.expected_exceptions)
     assert issubclass(Backoff, backoff_expected.expected_exceptions)
Beispiel #3
0
def test_cron_runs(timeout, concurrency, task_time, expected_calls,
                   container_factory, tracker):
    """Test running the cron main loop."""
    class Service(object):
        name = "service"

        @cron('* * * * * *', concurrency=concurrency)
        def tick(self):
            tracker()
            eventlet.sleep(task_time)

    container = container_factory(Service, {})

    # Check that Cron instance is initialized correctly
    instance = get_extension(container, Cron)
    assert instance.schedule == '* * * * * *'
    assert instance.tz is None
    assert instance.concurrency == concurrency

    with freezegun.freeze_time('2020-11-20 23:59:59.5', tick=True):
        container.start()
        eventlet.sleep(timeout)
        container.stop()

        assert tracker.call_count == expected_calls
Beispiel #4
0
    def test_json_payload(
        self, container_factory, config, web_session
    ):
        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @http('POST', '/resource')
            def resource(self, request):
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        submitted_data = {
            'foo': 'bar'
        }
        with entrypoint_waiter(container, 'resource'):
            rv = web_session.post('/resource', json=submitted_data)
            assert rv.status_code == 500
            assert "CustomException" in rv.text

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1
        _, kwargs = sentry.client.send.call_args

        received_data = kwargs['request']['data']
        assert received_data == json.dumps(submitted_data).encode('utf-8')
def test_cached_response(container):

    cached_rpc = get_extension(container, CachedRpcProxy)

    def fake_some_method(*args, **kwargs):
        return 'hi'

    with patch('nameko.rpc.MethodProxy.__call__', fake_some_method):
        with entrypoint_hook(container, 'cached') as hook:
            assert hook('test') == 'hi'

    def broken_some_method(*args, **kwargs):
        raise Exception('hmm')

    with patch('nameko.rpc.MethodProxy.__call__', broken_some_method):
        with entrypoint_hook(container, 'cached') as hook:
            assert hook('test') == 'hi'

    with patch('nameko.rpc.MethodProxy.__call__', broken_some_method):
        with entrypoint_hook(container, 'cached') as hook:
            with pytest.raises(Exception):
                hook('unknown')

    cached_rpc.cache = {}

    with patch('nameko.rpc.MethodProxy.__call__', broken_some_method):
        with entrypoint_hook(container, 'cached') as hook:
            with pytest.raises(Exception):
                hook('test')
Beispiel #6
0
    def test_unsupported_http_entrypoint(self, container_factory, config,
                                         web_session):
        bogus = object()

        class CustomHttpEntrypoint(HttpRequestHandler):
            def get_entrypoint_parameters(self, request):
                args = (bogus, request)
                kwargs = request.path_values
                return args, kwargs

        custom_http = CustomHttpEntrypoint.decorator

        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @custom_http('GET', '/resource')
            def resource(self, bogus_arg, request):
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        with entrypoint_waiter(container, 'resource'):
            web_session.get('/resource')

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1
        _, kwargs = sentry.client.send.call_args

        expected_http = {}
        assert kwargs['request'] == expected_http
Beispiel #7
0
    def test_tags_custom(self, container_factory, service_cls, config):

        config['SENTRY']['TAG_TYPE_CONTEXT_KEYS'] = ('session',
                                                     'other_pattern')

        container = container_factory(service_cls, config)
        container.start()

        context_data = {
            'call_id_stack': ["standalone_rpc_proxy.call.0"],
            'session_id': 1,
            'email_address': '*****@*****.**',
        }

        with ServiceRpcProxy('service', config,
                             context_data=context_data) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.broken()

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        expected_tags = {
            'site': config['SENTRY']['CLIENT_CONFIG']['site'],
            'call_id': 'service.broken.1',
            'parent_call_id': 'standalone_rpc_proxy.call.0',
            'service_name': 'service',
            'method_name': 'broken',
            'session_id': '1',  # extra
        }

        _, kwargs = sentry.client.send.call_args
        assert expected_tags == kwargs['tags']
Beispiel #8
0
    def test_user_defaults(self, container_factory, service_cls, config):

        user_data = {
            'user': '******',
            'username': '******',
            'user_id': 1,
            'email': '*****@*****.**',
            'email_address': '*****@*****.**',
            'session_id': 1
        }

        container = container_factory(service_cls, config)
        container.start()

        context_data = {
            'language': 'en-gb'
        }
        context_data.update(user_data)

        with ServiceRpcProxy(
            'service', config, context_data=context_data
        ) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.broken()

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        _, kwargs = sentry.client.send.call_args
        assert kwargs['user'] == user_data
Beispiel #9
0
    def test_concurrent_workers(
        self, container_factory, config, web_session
    ):

        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @http('GET', '/resource')
            def resource(self, request):
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        called = Mock()

        def called_twice(worker_ctx, res, exc_info):
            called()
            return called.call_count == 2

        with entrypoint_waiter(container, 'resource', callback=called_twice):
            eventlet.spawn(web_session.get, '/resource?q1')
            eventlet.spawn(web_session.get, '/resource?q2')

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 2
        query_strings = {
            kwargs['request']['query_string']
            for (_, kwargs) in sentry.client.send.call_args_list
        }
        assert query_strings == {"q1", "q2"}
Beispiel #10
0
    def test_activate_deactivate(self, container_factory, service_cls, config):

        container = container_factory(service_cls, config)
        container.start()

        with ServiceRpcProxy('service', config) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.activate_deactivate("a", "b", "c")

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        _, kwargs = sentry.client.send.call_args
        breadcrumbs = [
            crumb for crumb in kwargs['breadcrumbs']['values']
            if crumb['category'] == "worker"
        ]

        assert breadcrumbs == [{
            'category': "worker",
            'data': None,
            'level': ANY,
            'message': 'a',
            'timestamp': ANY,
            'type': 'default'
        }, {
            'category': "worker",
            'data': None,
            'level': ANY,
            'message': 'c',
            'timestamp': ANY,
            'type': 'default'
        }]
Beispiel #11
0
    def test_context_merge(self, container_factory, service_cls, config):

        container = container_factory(service_cls, config)
        container.start()

        user_data = {
            'user': '******'
        }
        context_data = {
            'language': 'en-gb'
        }
        context_data.update(user_data)

        data = {'foo': 'bar'}

        with ServiceRpcProxy(
            'service', config, context_data=context_data
        ) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.broken(data)

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        _, kwargs = sentry.client.send.call_args
        assert kwargs['user'] == user_data
        assert kwargs['arbitrary'] == data
Beispiel #12
0
    def test_client_disconnect(
        self, container_factory, config, web_session
    ):
        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @http('POST', '/resource')
            def resource(self, request):
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        request = Mock(
            method="GET",
            url="http://example.com",
            mimetype='application/json',
            environ={}
        )
        type(request).data = PropertyMock(side_effect=ClientDisconnected)

        with entrypoint_hook(container, 'resource') as hook:
            with pytest.raises(CustomException):
                hook(request)

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1
        _, kwargs = sentry.client.send.call_args

        assert kwargs['request']['data'] == {}
Beispiel #13
0
    def test_user_custom(self, container_factory, service_cls, config):

        config['SENTRY']['USER_TYPE_CONTEXT_KEYS'] = (
            'user|email',  # excludes session
            'other_pattern')

        container = container_factory(service_cls, config)
        container.start()

        user_data = {
            'user': '******',
            'username': '******',
            'user_id': 1,
            'email': '*****@*****.**',
            'email_address': '*****@*****.**',
        }

        context_data = {
            'session_id': 1,  # excluded from user data
            'language': 'en-gb'
        }
        context_data.update(user_data)

        with ServiceRpcProxy('service', config,
                             context_data=context_data) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.broken()

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        _, kwargs = sentry.client.send.call_args
        assert kwargs['user'] == user_data
        assert "session_id" not in kwargs['user']
def test_cached_response_on_timeout(container):

    cached_rpc = get_extension(container, CachedRpcProxy)

    def fake_some_method(*args, **kwargs):
        return 'hi'

    with patch('nameko.rpc.MethodProxy.__call__', fake_some_method):
        with entrypoint_hook(container, 'cached') as hook:
            assert hook() == 'hi'

    def slow_response(*args, **kwargs):
        eventlet.sleep(3)
        return 'hi'

    start = time.time()
    with patch('nameko.rpc.MethodProxy.__call__', slow_response):
        with entrypoint_hook(container, 'cached') as hook:
            assert hook() == 'hi'
    assert time.time() - start < 2

    cached_rpc.cache = {}

    start = time.time()
    with patch('nameko.rpc.MethodProxy.__call__', slow_response):
        with entrypoint_hook(container, 'cached') as hook:
            assert hook() == 'hi'
    assert time.time() - start >= 3
Beispiel #15
0
    def test_form_submission(
        self, container_factory, config, web_session
    ):
        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @http('POST', '/resource')
            def resource(self, request):
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        submitted_data = {
            'foo': 'bar'
        }
        with entrypoint_waiter(container, 'resource'):
            web_session.post('/resource', data=submitted_data)

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1
        _, kwargs = sentry.client.send.call_args

        assert kwargs['request']['data'] == submitted_data
Beispiel #16
0
    def test_extra(self, container_factory, service_cls, config):

        container = container_factory(service_cls, config)
        container.start()

        context_data = {
            'language': 'en-gb'
        }

        with ServiceRpcProxy(
            'service', config, context_data=context_data
        ) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.broken()

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        expected_extra = {
            'call_id_stack': (
                repr(u"standalone_rpc_proxy.call.0"), repr(u"service.broken.1")
            ),
            'language': repr(u"en-gb"),
            'sys.argv': ANY
        }

        _, kwargs = sentry.client.send.call_args
        assert kwargs['extra'] == expected_extra
Beispiel #17
0
    def test_normal_http_entrypoint(
        self, container_factory, config, web_session
    ):
        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @http('GET', '/resource')
            def resource(self, request):
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        with entrypoint_waiter(container, 'resource'):
            web_session.get('/resource')

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1
        _, kwargs = sentry.client.send.call_args

        expected_http = {
            'url': ANY,
            'query_string': "",
            'method': 'GET',
            'data': {},
            'headers': ANY,
            'env': ANY
        }
        assert kwargs['request'] == expected_http
Beispiel #18
0
def test_expected_exception_not_reported(
    exception_cls, expected_count, container_factory, config
):

    class Service(object):
        name = "service"

        sentry = SentryReporter()

        @rpc(expected_exceptions=CustomException)
        def broken(self):
            raise exception_cls("Error!")

    config['SENTRY']['REPORT_EXPECTED_EXCEPTIONS'] = False

    container = container_factory(Service, config)
    container.start()

    with entrypoint_waiter(container, 'broken') as result:
        with ServiceRpcProxy('service', config) as rpc_proxy:
            with pytest.raises(RemoteError):
                rpc_proxy.broken()

    with pytest.raises(exception_cls):
        result.get()

    sentry = get_extension(container, SentryReporter)

    assert sentry.client.send.call_count == expected_count
Beispiel #19
0
    def test_breadcrumbs(self, method, container_factory, service_cls, config):

        container = container_factory(service_cls, config)
        container.start()

        data = {'foo': 'bar'}

        with ServiceRpcProxy('service', config) as rpc_proxy:
            with pytest.raises(RemoteError):
                getattr(rpc_proxy, method)(data)

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 1

        _, kwargs = sentry.client.send.call_args
        breadcrumbs = [
            crumb for crumb in kwargs['breadcrumbs']['values']
            if crumb['category'] == "worker"
        ]

        assert breadcrumbs == [{
            'category': 'worker',
            'data': data,
            'level': 'warning',
            'message': 'breadcrumb message',
            'timestamp': ANY,
            'type': 'default'
        }]
Beispiel #20
0
    def test_concurrency(
        self, container_factory, config, web_session
    ):

        class Service(object):
            name = "service"

            sentry = SentryReporter()

            @http('GET', '/resource')
            def resource(self, request):
                breadcrumbs.record(message=request.query_string)
                raise CustomException()

        container = container_factory(Service, config)
        container.start()

        called = Mock()

        def called_twice(worker_ctx, res, exc_info):
            called()
            return called.call_count == 2

        with entrypoint_waiter(container, 'resource', callback=called_twice):
            eventlet.spawn(web_session.get, '/resource?q1')
            eventlet.spawn(web_session.get, '/resource?q2')

        sentry = get_extension(container, SentryReporter)

        assert sentry.client.send.call_count == 2

        breadcrumbs_map = {
            kwargs['request']['query_string']: kwargs['breadcrumbs']['values']
            for (_, kwargs) in sentry.client.send.call_args_list
        }

        expected_crumb_q1 = {
            'category': None,
            'data': None,
            'level': ANY,
            'message': 'q1'.encode('utf-8'),
            'timestamp': ANY,
            'type': 'default'
        }
        assert expected_crumb_q1 in breadcrumbs_map['q1']
        assert expected_crumb_q1 not in breadcrumbs_map['q2']

        expected_crumb_q2 = {
            'category': None,
            'data': None,
            'level': ANY,
            'message': 'q2'.encode('utf-8'),
            'timestamp': ANY,
            'type': 'default'
        }
        assert expected_crumb_q2 in breadcrumbs_map['q2']
        assert expected_crumb_q2 not in breadcrumbs_map['q1']
Beispiel #21
0
    def test_access_client(self, container_factory, service_cls, config):

        container = container_factory(service_cls, config)
        container.start()

        with ServiceRpcProxy('service', config) as rpc_proxy:
            res = rpc_proxy.get_dsn()

        sentry = get_extension(container, SentryReporter)
        assert res == sentry.client.get_public_dsn()
Beispiel #22
0
def test_worker_result(container_factory, service_cls, config):
    container = container_factory(service_cls, config)
    container.start()

    with entrypoint_hook(container, 'fine') as fine:
        with entrypoint_waiter(container, 'fine'):
            assert fine() == "OK"

    sentry = get_extension(container, SentryReporter)

    assert sentry.client.send.call_count == 0
Beispiel #23
0
def test_connection_not_found(container, websocket):
    hub = get_extension(container, WebSocketHubProvider)
    ws = websocket()
    hub.server.sockets.clear()

    # doesn't need to be known
    assert ws.rpc('unsubscribe') == 'unsubscribed!'

    with pytest.raises(RemoteError) as exc:
        ws.rpc('subscribe')
    assert exc.value.exc_type == 'ConnectionNotFound'
Beispiel #24
0
def test_connection_not_found(container, websocket):
    hub = get_extension(container, WebSocketHubProvider)
    ws = websocket()
    hub.server.sockets.clear()

    # doesn't need to be known
    assert ws.rpc('unsubscribe') == 'unsubscribed!'

    with pytest.raises(RemoteError) as exc:
        ws.rpc('subscribe')
    assert exc.value.exc_type == 'ConnectionNotFound'
Beispiel #25
0
def test_disabled(container_factory, service_cls, config):

    config['SENTRY']['DSN'] = None

    container = container_factory(service_cls, config)
    container.start()

    sentry = get_extension(container, SentryReporter)

    # DSN applied correctly
    assert sentry.client.get_public_dsn() is None
    assert not sentry.client.is_enabled()
Beispiel #26
0
def test_structlog_setup(container_factory, service_cls, config):
    container = container_factory(service_cls, config)
    container.start()

    struct_log = get_extension(container, StructlogDependency)

    with entrypoint_hook(container, 'foo') as foo:
        with entrypoint_waiter(container, 'foo'):
            assert foo() == 'OK'
            # StructlogDependency returns a structlog logger per service name
            service_logger = struct_log.logger_by_service_name['demo']
            assert 'bar' == service_logger.info('bar')
Beispiel #27
0
def test_setup_without_sentry_section_in_config(
    container_factory, service_cls, config
):
    del config['SENTRY']

    container = container_factory(service_cls, config)
    container.start()

    sentry = get_extension(container, SentryReporter)

    # DSN applied correctly
    assert sentry.client.get_public_dsn() is None
    assert not sentry.client.is_enabled()
Beispiel #28
0
    def test_get_redacted_args_invocation(self, args, kwargs):
        class Service(object):
            name = "service"

            @rpc(sensitive_variables="a")
            def method(self, a, b=None):
                pass

        expected = {'a': REDACTED, 'b': 'B'}

        container = ServiceContainer(Service, {})
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #29
0
def test_setup(container_factory, service_cls, config):

    container = container_factory(service_cls, config)
    container.start()

    sentry = get_extension(container, SentryReporter)

    # client config and DSN applied correctly
    assert sentry.client.site == "site name"
    assert sentry.client.get_public_dsn() == "//user@localhost:9000/1"
    assert sentry.client.is_enabled()

    # transport set correctly
    transport = sentry.client.remote.get_transport()
    assert isinstance(transport, EventletHTTPTransport)
Beispiel #30
0
    def test_get_redacted_args_invocation(self, args, kwargs, rabbit_config):

        class Service(object):
            name = "service"

            @rpc(sensitive_arguments="a")
            def method(self, a, b=None):
                pass  # pragma: no cover

        expected = {'a': REDACTED, 'b': 'B'}

        container = ServiceContainer(Service, rabbit_config)
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #31
0
    def test_get_redacted_args_invocation(self, args, kwargs, rabbit_config):

        class Service(object):
            name = "service"

            @rpc(sensitive_arguments="a")
            def method(self, a, b=None):
                pass  # pragma: no cover

        expected = {'a': REDACTED, 'b': 'B'}

        container = ServiceContainer(Service, rabbit_config)
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #32
0
    def test_get_redacted_args_invocation(self, args, kwargs):

        class Service(object):
            name = "service"

            @rpc(sensitive_variables="a")
            def method(self, a, b=None):
                pass

        expected = {'a': REDACTED, 'b': 'B'}

        container = ServiceContainer(Service, {})
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #33
0
def test_setup_without_optional_config(container_factory, service_cls, config):

    del config['SENTRY']['CLIENT_CONFIG']

    container = container_factory(service_cls, config)
    container.start()

    sentry = get_extension(container, SentryReporter)

    # DSN applied correctly
    assert sentry.client.get_public_dsn() == "//user@localhost:9000/1"
    assert sentry.client.is_enabled()

    # transport set correctly
    transport = sentry.client.remote.get_transport()
    assert isinstance(transport, EventletHTTPTransport)
Beispiel #34
0
    def test_get_redacted_args(self, sensitive_variables, expected):

        class Service(object):
            name = "service"

            @rpc(sensitive_variables=sensitive_variables)
            def method(self, a, b):
                pass

        args = ("A", "B")
        kwargs = {}

        container = ServiceContainer(Service, {})
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #35
0
    def test_get_redacted_args(
        self, sensitive_arguments, expected, rabbit_config
    ):

        class Service(object):
            name = "service"

            @rpc(sensitive_arguments=sensitive_arguments)
            def method(self, a, b):
                pass  # pragma: no cover

        args = ("A", "B")
        kwargs = {}

        container = ServiceContainer(Service, rabbit_config)
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #36
0
    def test_get_redacted_args_partial(self, sensitive_variables, expected):

        class Service(object):
            name = "service"

            @rpc(sensitive_variables=sensitive_variables)
            def method(self, a, b):
                pass

        complex_arg = {
            'foo': [1, 2, 3],
            'bar': "BAR"
        }

        args = ("A", complex_arg)
        kwargs = {}

        container = ServiceContainer(Service, {})
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected
Beispiel #37
0
    def test_get_redacted_args_partial(
        self, sensitive_arguments, expected, rabbit_config
    ):

        class Service(object):
            name = "service"

            @rpc(sensitive_arguments=sensitive_arguments)
            def method(self, a, b):
                pass  # pragma: no cover

        complex_arg = {
            'foo': [1, 2, 3],
            'bar': "BAR"
        }

        args = ("A", complex_arg)
        kwargs = {}

        container = ServiceContainer(Service, rabbit_config)
        entrypoint = get_extension(container, Rpc)

        redacted = get_redacted_args(entrypoint, *args, **kwargs)
        assert redacted == expected