async def test_fatal_error_stops_handler(registry, settings, handlers, extrahandlers, resource, cause_mock, cause_type, caplog, assert_logs, k8s_mocked): caplog.set_level(logging.DEBUG) name1 = f'{cause_type}_fn' event_type = None if cause_type == Reason.RESUME else 'irrelevant' cause_mock.reason = cause_type handlers.create_mock.side_effect = PermanentError("oops") handlers.update_mock.side_effect = PermanentError("oops") handlers.delete_mock.side_effect = PermanentError("oops") handlers.resume_mock.side_effect = PermanentError("oops") await process_resource_event( lifecycle=kopf.lifecycles.one_by_one, registry=registry, settings=settings, resource=resource, indexers=OperatorIndexers(), memories=ResourceMemories(), memobase=Memo(), raw_event={ 'type': event_type, 'object': {} }, event_queue=asyncio.Queue(), ) assert handlers.create_mock.call_count == (1 if cause_type == Reason.CREATE else 0) assert handlers.update_mock.call_count == (1 if cause_type == Reason.UPDATE else 0) assert handlers.delete_mock.call_count == (1 if cause_type == Reason.DELETE else 0) assert handlers.resume_mock.call_count == (1 if cause_type == Reason.RESUME else 0) assert not k8s_mocked.sleep_or_wait.called assert k8s_mocked.patch_obj.called patch = k8s_mocked.patch_obj.call_args_list[0][1]['patch'] assert patch['status']['kopf']['progress'] is not None assert patch['status']['kopf']['progress'][name1]['failure'] is True assert patch['status']['kopf']['progress'][name1]['message'] == 'oops' assert_logs([ "Handler .+ failed permanently: oops", ])
async def test_fatal_error_stops_handler(registry, handlers, extrahandlers, resource, cause_mock, cause_type, caplog, assert_logs, k8s_mocked): caplog.set_level(logging.DEBUG) name1 = f'{cause_type}_fn' cause_mock.event = cause_type handlers.create_mock.side_effect = PermanentError("oops") handlers.update_mock.side_effect = PermanentError("oops") handlers.delete_mock.side_effect = PermanentError("oops") handlers.resume_mock.side_effect = PermanentError("oops") await custom_object_handler( lifecycle=kopf.lifecycles.one_by_one, registry=registry, resource=resource, event={ 'type': 'irrelevant', 'object': cause_mock.body }, freeze=asyncio.Event(), replenished=asyncio.Event(), event_queue=asyncio.Queue(), ) assert handlers.create_mock.call_count == (1 if cause_type == CREATE else 0) assert handlers.update_mock.call_count == (1 if cause_type == UPDATE else 0) assert handlers.delete_mock.call_count == (1 if cause_type == DELETE else 0) assert handlers.resume_mock.call_count == (1 if cause_type == RESUME else 0) assert not k8s_mocked.sleep_or_wait.called assert k8s_mocked.patch_obj.called patch = k8s_mocked.patch_obj.call_args_list[0][1]['patch'] assert patch['status']['kopf']['progress'] is not None assert patch['status']['kopf']['progress'][name1][ 'failure'] # evals to true assert patch['status']['kopf']['progress'][name1]['message'] == 'oops' assert_logs([ "Handler .+ failed permanently: oops", ])
async def test_removed_and_remembered_on_permanent_errors( resource, settings, registry, memories, indexers, index, caplog, event_type, handlers): caplog.set_level(logging.DEBUG) body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}} memory = await memories.recall(raw_body=body) handlers.index_mock.side_effect = PermanentError("boo!") await process_resource_event( lifecycle=all_at_once, registry=registry, settings=settings, resource=resource, indexers=indexers, memories=memories, memobase=Memo(), raw_event={'type': event_type, 'object': body}, event_queue=asyncio.Queue(), resource_indexed=Toggle(), # used! only to enable indexing. ) assert set(index) == set() assert memory.indexing_state['index_fn'].finished == True assert memory.indexing_state['index_fn'].failure == True assert memory.indexing_state['index_fn'].success == False assert memory.indexing_state['index_fn'].message == 'boo!' assert memory.indexing_state['index_fn'].delayed == None
def sample_fn(**_): raise PermanentError("boo!")
def sample_fn2(**_): raise PermanentError("boo!456")
def sample_fn1(**_): raise PermanentError("boo!123")
async def fn(**kwargs): dummy.mock() dummy.kwargs = kwargs dummy.steps['called'].set() kwargs['stopped']._stopper.set(reason=kopf.DaemonStoppingReason.NONE) # to exit the cycle raise PermanentError("boo!")
async def fn(**kwargs): dummy.mock() dummy.kwargs = kwargs dummy.steps['called'].set() raise PermanentError("boo!")
assert response['response']['status'] == { 'message': exp_msg, 'code': exp_code } @pytest.mark.parametrize('error1, error2, exp_msg', [ pytest.param(Exception("err1"), Exception("err2"), "err1", id='builtin-first-samerank'), pytest.param(TemporaryError("err1"), TemporaryError("err2"), "err1", id='temp-first-samerank'), pytest.param(PermanentError("err1"), PermanentError("err2"), "err1", id='perm-first-samerank'), pytest.param(AdmissionError("err1"), AdmissionError("err2"), "err1", id='adms-first-samerank'), pytest.param(Exception("err1"), TemporaryError("err2"), "err2", id='temp-over-builtin'), pytest.param(Exception("err1"), AdmissionError("err2"), "err2", id='adms-over-builtin'),