diff --git a/kopf/reactor/registries.py b/kopf/reactor/registries.py index fb8d7e50..4f824fe3 100644 --- a/kopf/reactor/registries.py +++ b/kopf/reactor/registries.py @@ -621,7 +621,9 @@ def _matches_field( return (ignore_fields or not isinstance(handler, handlers.ResourceChangingHandler) or not handler.field or - any(field[:len(handler.field)] == handler.field for field in changed_fields)) + any(changed_field[:len(handler.field)] == handler.field or # a.b.c -vs- a.b => ignore c + changed_field == handler.field[:len(changed_field)] # a.b -vs- a.b.c => ignore c + for changed_field in changed_fields)) def _matches_labels( diff --git a/tests/registries/test_handler_matching.py b/tests/registries/test_handler_matching.py index e79f3429..08d63439 100644 --- a/tests/registries/test_handler_matching.py +++ b/tests/registries/test_handler_matching.py @@ -7,6 +7,7 @@ from kopf.reactor.causation import ResourceChangingCause from kopf.structs.bodies import Body from kopf.structs.dicts import parse_field +from kopf.structs.diffs import DiffOperation, DiffItem from kopf.structs.filters import MetaFilterToken from kopf.structs.handlers import ResourceChangingHandler, Reason, ALL_REASONS @@ -667,6 +668,50 @@ def some_fn(**_): ... handlers = registry.resource_changing_handlers[cause.resource].get_handlers(cause) assert not handlers + +# +# Special case for nested fields with shorter/longer diffs. +# + +def test_field_same_as_diff(cause_with_diff, registry, resource): + + @kopf.on.field(resource.group, resource.version, resource.plural, registry=registry, + field='level1.level2') + def some_fn(**_): ... + + cause = cause_with_diff + cause.reason = Reason.UPDATE + cause.diff = [DiffItem(DiffOperation.CHANGE, ('level1', 'level2'), 'old', 'new')] + handlers = registry.resource_changing_handlers[cause.resource].get_handlers(cause) + assert handlers + + +def test_field_longer_than_diff(cause_with_diff, registry, resource): + + @kopf.on.field(resource.group, resource.version, resource.plural, registry=registry, + field='level1.level2.level3') + def some_fn(**_): ... + + cause = cause_with_diff + cause.reason = Reason.UPDATE + cause.diff = [DiffItem(DiffOperation.CHANGE, ('level1', 'level2'), 'old', 'new')] + handlers = registry.resource_changing_handlers[cause.resource].get_handlers(cause) + assert handlers + + +def test_field_shorter_than_diff(cause_with_diff, registry, resource): + + @kopf.on.field(resource.group, resource.version, resource.plural, registry=registry, + field='level1') + def some_fn(**_): ... + + cause = cause_with_diff + cause.reason = Reason.UPDATE + cause.diff = [DiffItem(DiffOperation.CHANGE, ('level1', 'level2'), 'old', 'new')] + handlers = registry.resource_changing_handlers[cause.resource].get_handlers(cause) + assert handlers + + # # The handlers must be returned in order of registration, # even if they are mixed with-/without- * -event/-field handlers.