Пример #1
0
async def test_posting(resp_mocker, aresponses, hostname):

    post_mock = resp_mocker(return_value=aiohttp.web.json_response({}))
    aresponses.add(hostname, EVENTS_CORE_V1_CRD.get_url(namespace='ns'),
                   'post', post_mock)

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert post_mock.called
    assert post_mock.call_count == 1

    req = post_mock.call_args_list[0][0][0]  # [callidx][args/kwargs][argidx]
    assert req.method == 'POST'

    data = req.data
    assert data['type'] == 'type'
    assert data['reason'] == 'reason'
    assert data['message'] == 'message'
    assert data['source']['component'] == 'kopf'
    assert data['involvedObject']['apiVersion'] == 'group/version'
    assert data['involvedObject']['kind'] == 'kind'
    assert data['involvedObject']['namespace'] == 'ns'
    assert data['involvedObject']['name'] == 'name'
    assert data['involvedObject']['uid'] == 'uid'
Пример #2
0
async def test_headers_are_not_leaked(resp_mocker, aresponses, hostname,
                                      assert_logs, status):

    post_mock = resp_mocker(
        return_value=aresponses.Response(status=status, reason='boo!'))
    aresponses.add(hostname, EVENTS_CORE_V1_CRD.get_url(namespace='ns'),
                   'post', post_mock)

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert_logs([
        f"Failed to post an event. .* Status: {status}. Message: boo!",
    ],
                prohibited=[
                    "ClientResponseError",
                    "RequestInfo",
                    "headers=",
                ])
Пример #3
0
async def test_posting(req_mock):
    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert req_mock.post.called
    assert req_mock.post.call_count == 1

    data = json.loads(req_mock.post.call_args_list[0][1]['data'])
    assert data['type'] == 'type'
    assert data['reason'] == 'reason'
    assert data['message'] == 'message'
    assert data['source']['component'] == 'kopf'
    assert data['involvedObject']['apiVersion'] == 'group/version'
    assert data['involvedObject']['kind'] == 'kind'
    assert data['involvedObject']['namespace'] == 'ns'
    assert data['involvedObject']['name'] == 'name'
    assert data['involvedObject']['uid'] == 'uid'
Пример #4
0
async def test_message_is_cut_to_max_length(resp_mocker, aresponses, hostname):

    post_mock = resp_mocker(return_value=aiohttp.web.json_response({}))
    aresponses.add(hostname, EVENTS_CORE_V1_CRD.get_url(namespace='ns'),
                   'post', post_mock)

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    message = 'start' + ('x' * 2048) + 'end'
    await post_event(ref=ref, type='type', reason='reason', message=message)

    data = post_mock.call_args_list[0][0][
        0].data  # [callidx][args/kwargs][argidx]
    assert len(data['message']) <= 1024  # max supported API message length
    assert '...' in data['message']
    assert data['message'].startswith('start')
    assert data['message'].endswith('end')
Пример #5
0
def event(
    objs: Union[bodies.Body, Iterable[bodies.Body]],
    *,
    type: str,
    reason: str,
    message: str = '',
) -> None:
    for obj in cast(Iterator[bodies.Body], dicts.walk(objs)):
        ref = bodies.build_object_reference(obj)
        enqueue(ref=ref, type=type, reason=reason, message=message)
Пример #6
0
def info(
        objs: Union[bodies.Body, Iterable[bodies.Body]],
        *,
        reason: str,
        message: str = '',
) -> None:
    settings: configuration.OperatorSettings = settings_var.get()
    if settings.posting.enabled and settings.posting.level <= logging.INFO:
        for obj in cast(Iterator[bodies.Body], dicts.walk(objs)):
            ref = bodies.build_object_reference(obj)
            enqueue(ref=ref, type='Normal', reason=reason, message=message)
Пример #7
0
def event(
        objs: Union[bodies.Body, Iterable[bodies.Body]],
        *,
        type: str,
        reason: str,
        message: str = '',
) -> None:
    settings: configuration.OperatorSettings = settings_var.get()
    if settings.posting.enabled:
        for obj in cast(Iterator[bodies.Body], dicts.walk(objs)):
            ref = bodies.build_object_reference(obj)
            enqueue(ref=ref, type=type, reason=reason, message=message)
Пример #8
0
def exception(
        objs: Union[bodies.Body, Iterable[bodies.Body]],
        *,
        reason: str = '',
        message: str = '',
        exc: Optional[BaseException] = None,
) -> None:
    if exc is None:
        _, exc, _ = sys.exc_info()
    reason = reason if reason else type(exc).__name__
    message = f'{message} {exc}' if message and exc else f'{exc}' if exc else f'{message}'
    settings: configuration.OperatorSettings = settings_var.get()
    if settings.posting.enabled and settings.posting.level <= logging.ERROR:
        for obj in cast(Iterator[bodies.Body], dicts.walk(objs)):
            ref = bodies.build_object_reference(obj)
            enqueue(ref=ref, type='Error', reason=reason, message=message)
Пример #9
0
async def test_type_is_v1_not_v1beta1(req_mock):
    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert req_mock.post.called

    url = req_mock.post.call_args_list[0][1]['url']
    assert 'v1beta1' not in url
    assert '/api/v1/namespaces/ns/events' in url
Пример #10
0
async def test_message_is_cut_to_max_length(req_mock):
    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    message = 'start' + ('x' * 2048) + 'end'
    await post_event(ref=ref, type='type', reason='reason', message=message)

    data = json.loads(req_mock.post.call_args_list[0][1]['data'])
    assert len(data['message']) <= 1024  # max supported API message length
    assert '...' in data['message']
    assert data['message'].startswith('start')
    assert data['message'].endswith('end')
Пример #11
0
async def test_api_errors_logged_but_suppressed(resp_mocker, aresponses,
                                                hostname, assert_logs):

    post_mock = resp_mocker(return_value=aresponses.Response(status=555))
    aresponses.add(hostname, EVENTS_CORE_V1_CRD.get_url(namespace='ns'),
                   'post', post_mock)

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert post_mock.called
    assert_logs(["Failed to post an event."])
Пример #12
0
async def test_api_errors_logged_but_suppressed(req_mock, assert_logs):
    response = requests.Response()
    error = requests.exceptions.HTTPError("boo!", response=response)
    req_mock.post.side_effect = error

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert req_mock.post.called
    assert_logs([
        "Failed to post an event.*boo!",
    ])
Пример #13
0
async def test_regular_errors_escalate(req_mock):
    error = Exception('boo!')
    req_mock.post.side_effect = error

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)

    with pytest.raises(Exception) as excinfo:
        await post_event(ref=ref,
                         type='type',
                         reason='reason',
                         message='message')

    assert excinfo.value is error
Пример #14
0
async def test_type_is_v1_not_v1beta1(resp_mocker, aresponses, hostname):

    core_v1_mock = resp_mocker(return_value=aiohttp.web.json_response({}))
    v1beta1_mock = resp_mocker(return_value=aiohttp.web.json_response({}))
    aresponses.add(hostname, EVENTS_CORE_V1_CRD.get_url(namespace='ns'),
                   'post', core_v1_mock)
    aresponses.add(hostname, EVENTS_V1BETA1_CRD.get_url(namespace='ns'),
                   'post', v1beta1_mock)

    obj = {
        'apiVersion': 'group/version',
        'kind': 'kind',
        'metadata': {
            'namespace': 'ns',
            'name': 'name',
            'uid': 'uid'
        }
    }
    ref = build_object_reference(obj)
    await post_event(ref=ref, type='type', reason='reason', message='message')

    assert core_v1_mock.called
    assert not v1beta1_mock.called