def test_resources(): registry = OperatorRegistry() with pytest.deprecated_call(match=r"use @kopf.on"): registry.register_resource_watching_handler('group1', 'version1', 'plural1', some_fn) with pytest.deprecated_call(match=r"use @kopf.on"): registry.register_resource_changing_handler('group2', 'version2', 'plural2', some_fn) with pytest.deprecated_call(match=r"use @kopf.on"): registry.register_resource_watching_handler('group2', 'version2', 'plural2', some_fn) with pytest.deprecated_call(match=r"use @kopf.on"): registry.register_resource_changing_handler('group1', 'version1', 'plural1', some_fn) resources = registry.resources assert isinstance(resources, collections.abc.Collection) assert len(resources) == 2 resource1 = Resource('group1', 'version1', 'plural1') resource2 = Resource('group2', 'version2', 'plural2') assert resource1 in resources assert resource2 in resources
async def test_discovery_is_cached_per_session( resp_mocker, aresponses, hostname): res1info = {'name': 'someresources1', 'namespaced': True} res2info = {'name': 'someresources2', 'namespaced': True} result = {'resources': [res1info]} list_mock = resp_mocker(return_value=aiohttp.web.json_response(result)) aresponses.add(hostname, '/apis/some-group.org/someversion', 'get', list_mock) result = {'resources': [res2info]} list_mock = resp_mocker(return_value=aiohttp.web.json_response(result)) aresponses.add(hostname, '/apis/some-group.org/someversion', 'get', list_mock) resource = Resource('some-group.org', 'someversion', 'someresources1') info = await discover(resource=resource) assert info == res1info resource = Resource('some-group.org', 'someversion', 'someresources2') info = await discover(resource=resource) assert info is None # cached as absent on the 1st call. resource = Resource('some-group.org', 'someversion', 'someresources1') info = await discover(resource=resource) assert info == res1info
def test_resources(): registry = GlobalRegistry() registry.register_cause_handler('group1', 'version1', 'plural1', some_fn) registry.register_cause_handler('group2', 'version2', 'plural2', some_fn) resources = registry.resources assert isinstance(resources, collections.abc.Collection) assert len(resources) == 2 resource1 = Resource('group1', 'version1', 'plural1') resource2 = Resource('group2', 'version2', 'plural2') assert resource1 in resources assert resource2 in resources
def test_on_field_minimal(cause_factory): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') old = {'field': {'subfield': 'old'}} new = {'field': {'subfield': 'new'}} cause = cause_factory(resource=resource, reason=Reason.UPDATE, old=old, new=new, body=new) @kopf.on.field('group', 'version', 'plural', field='field.subfield') def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers( cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None assert handlers[0].field == ('field', 'subfield') assert handlers[0].value is None assert handlers[0].old is None assert handlers[0].new is None
def test_on_delete_minimal(cause_factory): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') cause = cause_factory(resource=resource, reason=Reason.DELETE) @kopf.on.delete('group', 'version', 'plural') def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers( cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.DELETE assert handlers[0].field is None assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None assert handlers[0].field is None assert handlers[0].old is None assert handlers[0].new is None
def test_on_field_with_all_kwargs(mocker): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') diff = [('op', ('field', 'subfield'), 'old', 'new')] cause = mocker.MagicMock(resource=resource, reason=Reason.UPDATE, diff=diff) mocker.patch('kopf.reactor.registries.match', return_value=True) @kopf.on.field('group', 'version', 'plural', 'field.subfield', id='id', timeout=123, registry=registry, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}) def fn(**_): pass handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field == ('field', 'subfield') assert handlers[0].id == 'id/field.subfield' assert handlers[0].timeout == 123 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'}
def test_on_create_with_all_kwargs(mocker): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') cause = mocker.MagicMock(resource=resource, reason=Reason.CREATE) mocker.patch('kopf.reactor.registries.match', return_value=True) @kopf.on.create('group', 'version', 'plural', id='id', timeout=123, registry=registry, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}) def fn(**_): pass handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.CREATE assert handlers[0].field is None assert handlers[0].id == 'id' assert handlers[0].timeout == 123 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'}
def test_on_field_minimal(mocker): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') diff = [('op', ('field', 'subfield'), 'old', 'new')] cause = mocker.MagicMock(resource=resource, reason=Reason.UPDATE, diff=diff) @kopf.on.field('group', 'version', 'plural', 'field.subfield') def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers( cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field == ('field', 'subfield') assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None
def test_on_field_minimal(cause_factory): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') old = {'field': {'subfield': 'old'}} new = {'field': {'subfield': 'new'}} cause = cause_factory(resource=resource, reason=Reason.UPDATE, old=old, new=new, body=new) @kopf.on.field('group', 'version', 'plural', field='field.subfield') def fn(**_): pass with pytest.deprecated_call(match=r"cease using the internal registries"): handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field == ('field', 'subfield') assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None
def test_on_field_with_cooldown(mocker, cause_factory): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') diff = [('op', ('field', 'subfield'), 'old', 'new')] cause = cause_factory(resource=resource, reason=Reason.UPDATE, diff=diff) mocker.patch('kopf.reactor.registries.match', return_value=True) with pytest.deprecated_call(match=r"use backoff="): @kopf.on.field('group', 'version', 'plural', field='field.subfield', cooldown=78) def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers( cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].backoff == 78 with pytest.deprecated_call(match=r"use handler.backoff"): assert handlers[0].cooldown == 78
def test_field_with_value(mocker, cause_factory, decorator, causeargs, handlers_prop): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') old = {'field': {'subfield': 'old'}} new = {'field': {'subfield': 'new'}} cause = cause_factory(resource=resource, old=old, new=new, body=new, **causeargs) mocker.patch('kopf.reactor.registries.match', return_value=True) @decorator('group', 'version', 'plural', registry=registry, field='spec.field', value='value') def fn(**_): pass handlers_registry = getattr(registry, handlers_prop) handlers = handlers_registry[resource].get_handlers(cause) assert len(handlers) == 1 assert handlers[0].field == ('spec', 'field') assert handlers[0].value == 'value'
def test_on_delete_with_all_kwargs(mocker, optional): registry = GlobalRegistry() resource = Resource('group', 'version', 'plural') cause = mocker.MagicMock(resource=resource, reason=Reason.DELETE) mocker.patch('kopf.reactor.registries.match', return_value=True) when = lambda **_: False @kopf.on.delete('group', 'version', 'plural', id='id', timeout=123, registry=registry, optional=optional, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}, when=when) def fn(**_): pass with pytest.deprecated_call( match=r"use OperatorRegistry.get_resource_changing_handlers\(\)"): handlers = registry.get_cause_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.DELETE assert handlers[0].field is None assert handlers[0].id == 'id' assert handlers[0].timeout == 123 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'} assert handlers[0].when == when
def test_on_update_with_all_kwargs(mocker): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') cause = mocker.MagicMock(resource=resource, reason=Reason.UPDATE) mocker.patch('kopf.reactor.registries.match', return_value=True) @kopf.on.update('group', 'version', 'plural', id='id', registry=registry, errors=ErrorsMode.PERMANENT, timeout=123, retries=456, backoff=78, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}) def fn(**_): pass handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.UPDATE assert handlers[0].field is None assert handlers[0].id == 'id' assert handlers[0].errors == ErrorsMode.PERMANENT assert handlers[0].timeout == 123 assert handlers[0].retries == 456 assert handlers[0].backoff == 78 assert handlers[0].cooldown == 78 # deprecated alias assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'}
def test_on_resume_minimal(mocker, reason): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') cause = mocker.MagicMock(resource=resource, reason=reason, initial=True, deleted=False) @kopf.on.resume('group', 'version', 'plural') def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers( cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field is None assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None
def test_on_create_minimal( cause_factory): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') cause = cause_factory(resource=resource, reason=Reason.CREATE) @kopf.on.create('group', 'version', 'plural') def fn(**_): pass with pytest.deprecated_call(match=r"use registry.resource_changing_handlers"): handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.CREATE assert handlers[0].field is None assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None
def test_on_delete_with_all_kwargs(mocker, optional): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') cause = mocker.MagicMock(resource=resource, reason=Reason.DELETE) mocker.patch('kopf.reactor.registries.match', return_value=True) when = lambda **_: False @kopf.on.delete('group', 'version', 'plural', id='id', registry=registry, errors=ErrorsMode.PERMANENT, timeout=123, retries=456, backoff=78, optional=optional, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}, when=when) def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.DELETE assert handlers[0].field is None assert handlers[0].id == 'id' assert handlers[0].errors == ErrorsMode.PERMANENT assert handlers[0].timeout == 123 assert handlers[0].retries == 456 assert handlers[0].backoff == 78 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'} assert handlers[0].when == when
def test_on_field_minimal( cause_factory): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') diff = [('op', ('field', 'subfield'), 'old', 'new')] cause = cause_factory(resource=resource, reason=Reason.UPDATE, diff=diff) @kopf.on.field('group', 'version', 'plural', 'field.subfield') def fn(**_): pass with pytest.deprecated_call(match=r"use registry.resource_changing_handlers"): handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field == ('field', 'subfield') assert handlers[0].errors is None assert handlers[0].timeout is None assert handlers[0].retries is None assert handlers[0].backoff is None assert handlers[0].labels is None assert handlers[0].annotations is None assert handlers[0].when is None
def test_on_update_with_all_kwargs( mocker, cause_factory): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') cause = cause_factory(resource=resource, reason=Reason.UPDATE) mocker.patch('kopf.reactor.registries.match', return_value=True) when = lambda **_: False @kopf.on.update('group', 'version', 'plural', id='id', registry=registry, errors=ErrorsMode.PERMANENT, timeout=123, retries=456, backoff=78, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}, when=when) def fn(**_): pass with pytest.deprecated_call(match=r"use registry.resource_changing_handlers"): handlers = registry.get_resource_changing_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.UPDATE assert handlers[0].field is None assert handlers[0].id == 'id' assert handlers[0].errors == ErrorsMode.PERMANENT assert handlers[0].timeout == 123 assert handlers[0].retries == 456 assert handlers[0].backoff == 78 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'} assert handlers[0].when == when
def test_on_update_with_all_kwargs(mocker, cause_factory): registry = GlobalRegistry() resource = Resource('group', 'version', 'plural') cause = cause_factory(resource=resource, reason=Reason.UPDATE) mocker.patch('kopf.reactor.registries.match', return_value=True) when = lambda **_: False @kopf.on.update('group', 'version', 'plural', id='id', timeout=123, registry=registry, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}, when=when) def fn(**_): pass with pytest.deprecated_call(match=r"cease using the internal registries"): handlers = registry.get_cause_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason == Reason.UPDATE assert handlers[0].field is None assert handlers[0].id == 'id' assert handlers[0].timeout == 123 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'} assert handlers[0].when == when
def test_on_field_with_all_kwargs(mocker, cause_factory): registry = GlobalRegistry() resource = Resource('group', 'version', 'plural') diff = [('op', ('field', 'subfield'), 'old', 'new')] cause = cause_factory(resource=resource, reason=Reason.UPDATE, diff=diff) mocker.patch('kopf.reactor.registries.match', return_value=True) when = lambda **_: False @kopf.on.field('group', 'version', 'plural', 'field.subfield', id='id', timeout=123, registry=registry, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}, when=when) def fn(**_): pass with pytest.deprecated_call( match=r"use OperatorRegistry.get_resource_changing_handlers\(\)"): handlers = registry.get_cause_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field == ('field', 'subfield') assert handlers[0].id == 'id/field.subfield' assert handlers[0].timeout == 123 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'} assert handlers[0].when == when
def test_on_field_with_all_kwargs(mocker): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') diff = [('op', ('field', 'subfield'), 'old', 'new')] cause = mocker.MagicMock(resource=resource, reason=Reason.UPDATE, diff=diff) mocker.patch('kopf.reactor.registries.match', return_value=True) when = lambda **_: False @kopf.on.field('group', 'version', 'plural', 'field.subfield', id='id', registry=registry, errors=ErrorsMode.PERMANENT, timeout=123, retries=456, backoff=78, labels={'somelabel': 'somevalue'}, annotations={'someanno': 'somevalue'}, when=when) def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers(cause) assert len(handlers) == 1 assert handlers[0].fn is fn assert handlers[0].reason is None assert handlers[0].field ==('field', 'subfield') assert handlers[0].id == 'id/field.subfield' assert handlers[0].errors == ErrorsMode.PERMANENT assert handlers[0].timeout == 123 assert handlers[0].retries == 456 assert handlers[0].backoff == 78 assert handlers[0].labels == {'somelabel': 'somevalue'} assert handlers[0].annotations == {'someanno': 'somevalue'} assert handlers[0].when == when
def test_creation_with_all_kwargs(): resource = Resource( group='group', version='version', plural='plural', ) assert resource.group == 'group' assert resource.version == 'version' assert resource.plural == 'plural'
async def test_discovery_of_unexisting_group_or_version( resp_mocker, aresponses, hostname, status): list_mock = resp_mocker(return_value=aresponses.Response(status=status, reason="boo!")) aresponses.add(hostname, '/apis/some-group.org/someversion', 'get', list_mock) resource = Resource('some-group.org', 'someversion', 'someresources') info = await discover(resource=resource) assert info is None
def test_resources(): handler = Mock() resource1 = Resource('group1', 'version1', 'plural1') resource2 = Resource('group2', 'version2', 'plural2') registry = OperatorRegistry() registry.resource_watching_handlers[resource1].append(handler) registry.resource_changing_handlers[resource2].append(handler) registry.resource_watching_handlers[resource2].append(handler) registry.resource_changing_handlers[resource1].append(handler) resources = registry.resources assert isinstance(resources, collections.abc.Collection) assert len(resources) == 2 assert resource1 in resources assert resource2 in resources
def test_resumes_ignored_for_non_initial_causes(mocker, reason, deleted): registry = kopf.get_default_registry() resource = Resource('group', 'version', 'plural') cause = mocker.MagicMock(resource=resource, reason=reason, initial=False, deleted=deleted) @kopf.on.resume('group', 'version', 'plural') def fn(**_): pass handlers = registry.resource_changing_handlers[resource].get_handlers(cause) assert len(handlers) == 0
def test_requires_finalizer_deletion_handler(optional, expected): registry = GlobalRegistry() resource = Resource('group', 'version', 'plural') @kopf.on.delete('group', 'version', 'plural', registry=registry, optional=optional) def fn(**_): pass requires_finalizer = registry.requires_finalizer(resource=resource, cause=CAUSE) assert requires_finalizer == expected
async def test_discovery_of_unexisting_resource( resp_mocker, aresponses, hostname): result = {'resources': []} list_mock = resp_mocker(return_value=aiohttp.web.json_response(result)) aresponses.add(hostname, '/apis/some-group.org/someversion', 'get', list_mock) resource = Resource('some-group.org', 'someversion', 'someresources') info = await discover(resource=resource) assert info is None
def test_requires_finalizer_no_deletion_handler(): registry = GlobalRegistry() resource = Resource('group', 'version', 'plural') @kopf.on.create('group', 'version', 'plural', registry=registry) def fn1(**_): pass requires_finalizer = registry.requires_finalizer(resource=resource, body=OBJECT_BODY) assert requires_finalizer is False
def test_requires_finalizer_no_deletion_handler(): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') @kopf.on.create('group', 'version', 'plural', registry=registry) def fn1(**_): pass requires_finalizer = registry.resource_changing_handlers[ resource].requires_finalizer(CAUSE) assert requires_finalizer is False
def test_requires_finalizer_no_deletion_handler(): registry = OperatorRegistry() resource = Resource('group', 'version', 'plural') @kopf.on.create('group', 'version', 'plural', registry=registry) def fn1(**_): pass with pytest.deprecated_call(match=r"use registry.resource_changing_handlers"): requires_finalizer = registry.requires_finalizer(resource=resource, cause=CAUSE) assert requires_finalizer is False