fix: raise ValueError for unknown label selector operators#721
fix: raise ValueError for unknown label selector operators#721raballew wants to merge 13 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughSelector matching now evaluates matchExpressions against matchLabels when exact expression matches are not found. A new ChangesLabel Selector Expression Evaluation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
python/packages/jumpstarter/jumpstarter/client/selectors.py (1)
89-93: 💤 Low valueConsider updating the docstring to reflect fallback behavior.
The docstring states matchExpressions must be "present" in selector, but the new implementation allows matchLabels to satisfy matchExpressions via
_label_satisfies_expression. The inline comment at lines 106-107 accurately describes "satisfied by selector's matchExpressions or matchLabels," but the function docstring could be updated to match.📝 Suggested docstring update
def selector_contains(selector: str, requirements: str) -> bool: - """Check if selector contains all criteria from requirements. + """Check if selector satisfies all criteria from requirements. - Returns True if all matchLabels and matchExpressions in `requirements` - are present in `selector`. + Returns True if all matchLabels in `requirements` are present in `selector` + and all matchExpressions in `requirements` are satisfied by `selector` + (either by exact match in matchExpressions or by evaluation against matchLabels). """🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@python/packages/jumpstarter/jumpstarter/client/selectors.py` around lines 89 - 93, The selector_contains docstring is out-of-date about matchExpressions: update the docstring for selector_contains to state that requirements' matchExpressions may be satisfied either by selector's matchExpressions or by selector's matchLabels (via the helper _label_satisfies_expression), and clarify the fallback behavior so the function docstring matches the inline comment and current implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@python/packages/jumpstarter/jumpstarter/client/selectors.py`:
- Around line 89-93: The selector_contains docstring is out-of-date about
matchExpressions: update the docstring for selector_contains to state that
requirements' matchExpressions may be satisfied either by selector's
matchExpressions or by selector's matchLabels (via the helper
_label_satisfies_expression), and clarify the fallback behavior so the function
docstring matches the inline comment and current implementation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f597acb7-6ece-444b-ad51-d76db918a07b
📒 Files selected for processing (2)
python/packages/jumpstarter/jumpstarter/client/selectors.pypython/packages/jumpstarter/jumpstarter/client/selectors_test.py
There was a problem hiding this comment.
🧹 Nitpick comments (1)
python/packages/jumpstarter/jumpstarter/client/grpc.py (1)
381-383: ⚡ Quick winInclude the caught error text in the warning.
Line 382 logs that evaluation failed but drops the actual
ValueError, which makes malformed selector diagnosis harder.♻️ Suggested patch
- except ValueError: - logger.warning("skipping lease %s: unable to evaluate selector %r", lease.name, lease.selector) + except ValueError as exc: + logger.warning( + "skipping lease %s: unable to evaluate selector %r (%s)", + lease.name, + lease.selector, + exc, + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@python/packages/jumpstarter/jumpstarter/client/grpc.py` around lines 381 - 383, The warning for a failed selector evaluation in the Lease filtering code drops the ValueError details; update the except ValueError handler in the function that builds the LeaseList (where lease, lease.selector and filtered are used) to capture the exception (e.g., except ValueError as e) and include the exception text in the logger.warning call so the message includes both the lease name, selector and the caught error information for easier diagnosis.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@python/packages/jumpstarter/jumpstarter/client/grpc.py`:
- Around line 381-383: The warning for a failed selector evaluation in the Lease
filtering code drops the ValueError details; update the except ValueError
handler in the function that builds the LeaseList (where lease, lease.selector
and filtered are used) to capture the exception (e.g., except ValueError as e)
and include the exception text in the logger.warning call so the message
includes both the lease name, selector and the caught error information for
easier diagnosis.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e0048d6c-538c-4151-af6b-ed75ec87a5f1
📒 Files selected for processing (2)
python/packages/jumpstarter/jumpstarter/client/grpc.pypython/packages/jumpstarter/jumpstarter/client/grpc_test.py
…ents Cherry-picked from 14f0220 to provide the _label_satisfies_expression function that this branch will fix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_label_satisfies_expression silently returned False for unrecognized operator strings, masking bugs in callers. Now raises ValueError with a message including the invalid operator. Also adds explicit handling for the !exists operator when the key is present. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… fallback Cover the fallback path where selector_contains uses _label_satisfies_expression when no matching expression is found in sel_exprs. This verifies that matchLabels correctly satisfy "in" and "notin" matchExpression requirements. Generated-By: Forge/20260601_094535_362027_58545917 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the !exists check before the key-presence guard so that DoesNotExist correctly returns True when the key is missing from labels, matching Kubernetes semantics. Update the selector_contains test to reflect the corrected behavior. Generated-By: Forge/20260605_210046_334143_d93db272 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The docstring previously stated that matchExpressions must be "present" in the selector, but after the label-to-expression fallback change they are now "satisfied" by evaluation against matchLabels. Generated-By: Forge/20260605_210046_334143_d93db272 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add docstring with Raises section so callers are aware that an unrecognized operator will raise ValueError. Generated-By: Forge/20260605_210046_334143_d93db272 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify that _label_satisfies_expression returns False for the exists operator when the key is not present in the labels, preventing regressions in the key-presence guard logic. Generated-By: Forge/20260605_210046_334143_d93db272 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Catch ValueError raised by _label_satisfies_expression so that a single lease with an unrecognised operator does not break the entire filter operation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
b61a580 to
1d2c92e
Compare
|
You create two exporters:
You run @maboras-rh @mangelajo what do you expect to see? |
I think we should just do whatever kubernetes does in this case, which... I don't know what it is :D |
this is a valid design question. The fallback treats the selector's
It says nothing about whether the exporter has a production label. the actual exporter behind that lease could have |
|
and even this might not be true because the exporter object could have changed in the meantime - so the lease holds a snapshot of an old exporter? In this case the lease would need to carry its own context and we have two options:
|
|
k8s has no concept of "one selector contains another". It only evaluates selectors against concrete label sets. selector_contains is a custom abstraction - it treats one selector's matchLabels as a proxy for resource labels and evaluates the other selector's expressions against them which has no k8s counterpart. |
In Kubernetes, NotIn and NotEquals return true when the key is absent from the label set. The previous implementation returned false for all operators when the key was absent (except !exists), which diverged from k8s behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest commit fixes Kubernetes compatibility for In Kubernetes, Concrete examples that were wrong before:
The fix moves Tests now cover all 7 Kubernetes label selector operators ( |
The !production filter now correctly matches leases where the key is absent. Add a !example.com/board negative test to cover the case where the key is present and !exists should fail. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
_label_satisfies_expressionnow raisesValueErrorfor unrecognized operators instead of silently returningFalseselector_containsfalls back to_label_satisfies_expressionwhen a required matchExpression has no matching expression in the selector but matchLabels may satisfy itCloses #718
Test plan
_label_satisfies_expression("", ...)raisesValueError_label_satisfies_expression("bogus", ...)raisesValueErrorwith operator in messagein,notin,exists,!exists,!=) still work correctlyselector_containslabel-to-expression fallback works forin/notin🤖 Generated with Claude Code