Ejemplo n.º 1
0
def test_started_from_storage(storage, handler, body, expected):
    patch = Patch()
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.store(body=Body({}), patch=patch, storage=storage)
    assert patch['status']['kopf']['progress']['some-id'][
        'started'] == expected
Ejemplo n.º 2
0
def test_get_retry_count(storage, handler, expected, body):
    origbody = copy.deepcopy(body)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    result = state[handler.id].retries
    assert result == expected
    assert body == origbody  # not modified
Ejemplo n.º 3
0
def test_sleeping_flag(storage, handler, expected, body):
    origbody = copy.deepcopy(body)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    result = state[handler.id].sleeping
    assert result == expected
    assert body == origbody  # not modified
Ejemplo n.º 4
0
def test_created_from_purposeless_storage(storage, handler):
    body = {'status': {'kopf': {'progress': {'some-id': {'purpose': None}}}}}
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    assert len(state) == 1
    assert state.purpose is None
    assert state['some-id'].purpose is None
Ejemplo n.º 5
0
def test_repurposed_not_affecting_the_existing_handlers_from_scratch(
        handler, reason):
    state = State.from_scratch()
    state = state.with_handlers([handler]).with_purpose(reason).with_handlers(
        [handler])
    assert len(state) == 1
    assert state.purpose is reason
    assert state['some-id'].purpose is None
Ejemplo n.º 6
0
def test_purge_progress_when_known_at_restoration_only(storage, handler):
    body = {'status': {'kopf': {'progress': {'some-id': {'retries': 5}}}}}
    patch = Patch()
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.purge(patch=patch, body=Body(body), storage=storage, handlers=[])
    assert patch == {'status': {'kopf': {'progress': {'some-id': None}}}}
Ejemplo n.º 7
0
def test_awakening_time(storage, handler, expected, body):
    origbody = copy.deepcopy(body)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    result = state[handler.id].delayed
    assert result == expected
    assert body == origbody  # not modified
Ejemplo n.º 8
0
def test_created_empty_from_scratch():
    state = State.from_scratch()
    assert len(state) == 0
    assert state.purpose is None
    assert state.done == True
    assert state.delay is None
    assert state.delays == []
    assert state.counts == StateCounters(success=0, failure=0, running=0)
    assert state.extras == {}
Ejemplo n.º 9
0
def test_set_retry_time(storage, handler, expected_retries, expected_delayed, body, delay):
    origbody = copy.deepcopy(body)
    patch = Patch()
    state = State.from_storage(body=Body(body), handlers=[handler], storage=storage)
    state = state.with_outcomes(outcomes={handler.id: HandlerOutcome(final=False, delay=delay)})
    state.store(patch=patch, body=Body(body), storage=storage)
    assert patch['status']['kopf']['progress']['some-id']['retries'] == expected_retries
    assert patch['status']['kopf']['progress']['some-id']['delayed'] == expected_delayed
    assert body == origbody  # not modified
Ejemplo n.º 10
0
def test_purge_progress_when_exists_in_body(storage, handler):
    body = {'status': {'kopf': {'progress': {'some-id': {'retries': 5}}}}}
    patch = Patch()
    origbody = copy.deepcopy(body)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.purge(patch=patch, body=Body(body), storage=storage)
    assert patch == {'status': {'kopf': {'progress': {'some-id': None}}}}
    assert body == origbody  # not modified
Ejemplo n.º 11
0
def test_created_empty_from_filled_storage_without_handlers(
        storage, handler, body):
    state = State.from_storage(body=Body(body), handlers=[], storage=storage)
    assert len(state) == 0
    assert state.purpose is None
    assert state.done == True
    assert state.delay is None
    assert state.delays == []
    assert state.counts == StateCounters(success=0, failure=0, running=0)
    assert state.extras == {}
Ejemplo n.º 12
0
def test_purge_progress_when_already_empty_in_body_and_patch(storage, handler):
    body = {}
    patch = Patch()
    origbody = copy.deepcopy(body)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.purge(patch=patch, body=Body(body), storage=storage)
    assert not patch
    assert body == origbody  # not modified
Ejemplo n.º 13
0
def test_subrefs_ignored_when_not_specified(storage, handler):
    body = {}
    patch = Patch()
    outcome = HandlerOutcome(final=True, subrefs=[])
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_outcomes(outcomes={handler.id: outcome})
    state.store(patch=patch, body=Body(body), storage=storage)
    assert patch['status']['kopf']['progress']['some-id']['subrefs'] is None
Ejemplo n.º 14
0
def test_purge_progress_when_already_empty_in_body_and_patch(storage, handler):
    body = {}
    patch = Patch()
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.purge(patch=patch,
                body=Body(body),
                storage=storage,
                handlers=[handler])
    assert not patch
Ejemplo n.º 15
0
def test_set_awake_time(storage, handler, expected, body, delay):
    patch = Patch()
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_handlers([handler])
    state = state.with_outcomes(
        outcomes={handler.id: HandlerOutcome(final=False, delay=delay)})
    state.store(patch=patch, body=Body(body), storage=storage)
    assert patch['status']['kopf']['progress']['some-id'].get(
        'delayed') == expected
Ejemplo n.º 16
0
def test_asap_takes_the_first_one_when_no_retries(mocker):
    handler1 = mocker.Mock(id='id1', spec_set=['id'])
    handler2 = mocker.Mock(id='id2', spec_set=['id'])
    handler3 = mocker.Mock(id='id3', spec_set=['id'])

    state = State.from_scratch().with_handlers([handler1, handler2, handler3])
    handlers = [handler1, handler2, handler3]
    selected = kopf.lifecycles.asap(handlers, state=state)
    assert isinstance(selected, (tuple, list))
    assert len(selected) == 1
    assert selected[0] is handler1
Ejemplo n.º 17
0
def test_always_started_when_created_from_body(storage, handler, body,
                                               expected):
    origbody = copy.deepcopy(body)
    patch = Patch()
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.store(body=Body({}), patch=patch, storage=storage)
    assert patch['status']['kopf']['progress']['some-id'][
        'started'] == expected
    assert body == origbody  # not modified
Ejemplo n.º 18
0
def test_repurposed_not_affecting_the_existing_handlers_from_storage(
        storage, handler, reason):
    body = {'status': {'kopf': {'progress': {'some-id': {'purpose': None}}}}}
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_handlers([handler]).with_purpose(reason).with_handlers(
        [handler])
    assert len(state) == 1
    assert state.purpose is reason
    assert state['some-id'].purpose is None
Ejemplo n.º 19
0
def test_store_success(storage, handler, expected_retries, expected_stopped, body):
    origbody = copy.deepcopy(body)
    patch = Patch()
    state = State.from_storage(body=Body(body), handlers=[handler], storage=storage)
    state = state.with_outcomes(outcomes={handler.id: HandlerOutcome(final=True)})
    state.store(patch=patch, body=Body(body), storage=storage)
    assert patch['status']['kopf']['progress']['some-id']['success'] is True
    assert patch['status']['kopf']['progress']['some-id']['failure'] is False
    assert patch['status']['kopf']['progress']['some-id']['retries'] == expected_retries
    assert patch['status']['kopf']['progress']['some-id']['stopped'] == expected_stopped
    assert patch['status']['kopf']['progress']['some-id']['message'] is None
    assert body == origbody  # not modified
Ejemplo n.º 20
0
def test_issue_601_deletion_supersedes_other_processing(storage, reason):

    body = {
        'status': {
            'kopf': {
                'progress': {
                    'fn1': {
                        'purpose': reason.value,
                        'failure': True
                    },
                    'fn2': {
                        'purpose': reason.value,
                        'success': True
                    },
                    'fn3': {
                        'purpose': reason.value,
                        'delayed': TS1_ISO
                    },
                }
            }
        }
    }
    create_handler1 = Mock(id='fn1', spec_set=['id'])
    create_handler2 = Mock(id='fn2', spec_set=['id'])
    create_handler3 = Mock(id='fn3', spec_set=['id'])
    delete_handler9 = Mock(id='delete_fn', spec_set=['id'])
    owned_handlers = [
        create_handler1, create_handler2, create_handler3, delete_handler9
    ]
    cause_handlers = [delete_handler9]

    state = State.from_storage(body=Body(body),
                               handlers=owned_handlers,
                               storage=storage)
    state = state.with_purpose(Reason.DELETE)
    state = state.with_handlers(cause_handlers)

    assert len(state) == 4
    assert state.extras == {
        reason: StateCounters(success=1, failure=1, running=1)
    }
    assert state.counts == StateCounters(success=0, failure=0, running=1)
    assert state.done == False
    assert state.delays == [0.0]

    state = state.with_outcomes({'delete_fn': HandlerOutcome(final=True)})

    assert state.extras == {
        reason: StateCounters(success=1, failure=1, running=1)
    }
    assert state.counts == StateCounters(success=1, failure=0, running=0)
    assert state.done == True
    assert state.delays == []
Ejemplo n.º 21
0
def test_started_from_storage_is_preferred_over_from_scratch(
        storage, handler, body, expected):
    with freezegun.freeze_time(TS0):
        state = State.from_storage(body=Body(body),
                                   handlers=[handler],
                                   storage=storage)
    with freezegun.freeze_time(TS1):
        state = state.with_handlers([handler])
    patch = Patch()
    state.store(body=Body({}), patch=patch, storage=storage)
    assert patch['status']['kopf']['progress']['some-id'][
        'started'] == expected
Ejemplo n.º 22
0
def test_with_handlers_relevant_to_the_purpose(storage, handler, body,
                                               expected_counts, expected_done,
                                               expected_delays, reason):
    body['status']['kopf']['progress']['some-id']['purpose'] = reason.value
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_purpose(reason)
    assert len(state) == 1
    assert state.extras == {}
    assert state.counts == expected_counts
    assert state.done == expected_done
    assert state.delays == expected_delays
Ejemplo n.º 23
0
def test_subrefs_added_to_empty_state(storage, handler):
    body = {}
    patch = Patch()
    outcome_subrefs = ['sub2/b', 'sub2/a', 'sub2', 'sub1', 'sub3']
    expected_subrefs = ['sub1', 'sub2', 'sub2/a', 'sub2/b', 'sub3']
    outcome = HandlerOutcome(final=True, subrefs=outcome_subrefs)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_outcomes(outcomes={handler.id: outcome})
    state.store(patch=patch, body=Body(body), storage=storage)
    assert patch['status']['kopf']['progress']['some-id'][
        'subrefs'] == expected_subrefs
Ejemplo n.º 24
0
def test_with_handlers_irrelevant_to_the_purpose(storage, handler, body,
                                                 expected_extras,
                                                 stored_reason,
                                                 processed_reason):
    body['status']['kopf']['progress']['some-id'][
        'purpose'] = stored_reason.value
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_purpose(processed_reason)
    assert len(state) == 1
    assert state.extras[stored_reason] == expected_extras
    assert state.counts == StateCounters(success=0, failure=0, running=0)
    assert state.done == True
    assert state.delays == []
Ejemplo n.º 25
0
def test_asap_takes_the_least_retried(mocker):
    handler1 = mocker.Mock(id='id1', spec_set=['id'])
    handler2 = mocker.Mock(id='id2', spec_set=['id'])
    handler3 = mocker.Mock(id='id3', spec_set=['id'])

    # Set the pre-existing state, and verify that it was set properly.
    state = State.from_scratch().with_handlers([handler1, handler2, handler3])
    state = state.with_outcomes({handler1.id: HandlerOutcome(final=False)})
    state = state.with_outcomes({handler1.id: HandlerOutcome(final=False)})
    state = state.with_outcomes({handler3.id: HandlerOutcome(final=False)})
    assert state[handler1.id].retries == 2
    assert state[handler2.id].retries == 0
    assert state[handler3.id].retries == 1

    handlers = [handler1, handler2, handler3]
    selected = kopf.lifecycles.asap(handlers, state=state)
    assert isinstance(selected, (tuple, list))
    assert len(selected) == 1
    assert selected[0] is handler2
Ejemplo n.º 26
0
async def test_permanent_failures_are_not_reindexed(
        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)
    memory.indexing_state = State({'index_fn': HandlerState(failure=True)})
    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 handlers.index_mock.call_count == 0
Ejemplo n.º 27
0
def test_store_failure(storage, handler, expected_retries, expected_stopped,
                       body):
    error = Exception('some-error')
    patch = Patch()
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state = state.with_handlers([handler])
    state = state.with_outcomes(
        outcomes={handler.id: HandlerOutcome(final=True, exception=error)})
    state.store(patch=patch, body=Body(body), storage=storage)
    assert patch['status']['kopf']['progress']['some-id']['success'] is False
    assert patch['status']['kopf']['progress']['some-id']['failure'] is True
    assert patch['status']['kopf']['progress']['some-id'][
        'retries'] == expected_retries
    assert patch['status']['kopf']['progress']['some-id'][
        'stopped'] == expected_stopped
    assert patch['status']['kopf']['progress']['some-id'][
        'message'] == 'some-error'
Ejemplo n.º 28
0
async def test_protocol_invocation(lifecycle, resource):
    """
    To be sure that all kwargs are accepted properly.
    Especially when the new kwargs are added or an invocation protocol changed.
    """
    # The values are irrelevant, they can be anything.
    state = State.from_scratch(handlers=[])
    cause = ResourceChangingCause(
        logger=logging.getLogger('kopf.test.fake.logger'),
        resource=resource,
        patch=Patch(),
        memo=Memo(),
        body=Body({}),
        initial=False,
        reason=Reason.NOOP,
    )
    handlers = []
    selected = await invoke(lifecycle, handlers, cause=cause, state=state)
    assert isinstance(selected, (tuple, list))
    assert len(selected) == 0
Ejemplo n.º 29
0
async def test_temporary_failures_with_expired_delays_are_reindexed(
        resource, settings, registry, memories, indexers, index, caplog, event_type, handlers):
    caplog.set_level(logging.DEBUG)
    body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}}
    delayed = datetime.datetime(2020, 12, 31, 23, 59, 59, 0)
    memory = await memories.recall(raw_body=body)
    memory.indexing_state = State({'index_fn': HandlerState(delayed=delayed)})
    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 handlers.index_mock.call_count == 1
Ejemplo n.º 30
0
def test_purge_progress_when_already_empty_in_body_but_not_in__patch(
        storage, handler):
    body = {}
    patch = Patch(
        {'status': {
            'kopf': {
                'progress': {
                    'some-id': {
                        'retries': 5
                    }
                }
            }
        }})
    origbody = copy.deepcopy(body)
    state = State.from_storage(body=Body(body),
                               handlers=[handler],
                               storage=storage)
    state.purge(patch=patch, body=Body(body), storage=storage)
    assert not patch
    assert body == origbody  # not modified