ROX-33799: replace detector.New() with builder pattern#19741
ROX-33799: replace detector.New() with builder pattern#19741
Conversation
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- Consider having
Buildreturn(Detector, error)and validating that all required dependencies (e.g.,clusterID,enforcer, stores, label providers) are set, rather than silently constructing adetectorImplwith nil fields. - Now that
ClusterIDProvideris exported and used as part of the builder’s public API, it may be worth adding clarification (in comments or type naming) about whetherGetvsGetNoWaithave any ordering/initialization guarantees that callers must respect. - If the longer-term plan is to introduce a
StoreProviderto simplify the builder, you might want to leave a TODO near the multipleWith*Storemethods inbuilder.goto capture that intended follow-up refactor in context.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider having `Build` return `(Detector, error)` and validating that all required dependencies (e.g., `clusterID`, `enforcer`, stores, label providers) are set, rather than silently constructing a `detectorImpl` with nil fields.
- Now that `ClusterIDProvider` is exported and used as part of the builder’s public API, it may be worth adding clarification (in comments or type naming) about whether `Get` vs `GetNoWait` have any ordering/initialization guarantees that callers must respect.
- If the longer-term plan is to introduce a `StoreProvider` to simplify the builder, you might want to leave a TODO near the multiple `With*Store` methods in `builder.go` to capture that intended follow-up refactor in context.
## Individual Comments
### Comment 1
<location path="sensor/common/detector/builder.go" line_range="118-119" />
<code_context>
+ return b
+}
+
+// Build creates a new Detector from the builder configuration.
+func (b *Builder) Build() Detector {
+ detectorStopper := concurrency.NewStopper()
+ netFlowQueueSize := queueScaler.ScaleSizeOnNonDefault(env.DetectorNetworkFlowBufferSize)
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider validating required fields in Build (and/or returning an error) instead of silently constructing with possible nil dependencies.
With the builder pattern, a `Detector` can now be built without setting critical dependencies (`clusterID`, `enforcer`, stores, label providers, etc.), leaving them nil and causing hard-to-trace panics later. Please make `Build` validate required fields—either by returning `(Detector, error)` on missing dependencies or by panicking with a clear message—so misconfiguration fails fast at construction time.
Suggested implementation:
```golang
// Build creates a new Detector from the builder configuration.
func (b *Builder) Build() Detector {
// Fail fast on misconfiguration: ensure required dependencies are set.
if b.clusterLabelProvider == nil {
panic("detector.Builder.Build: clusterLabelProvider must be set; call WithClusterLabelProvider before Build")
}
if b.namespaceLabelProvider == nil {
panic("detector.Builder.Build: namespaceLabelProvider must be set; call WithNamespaceLabelProvider before Build")
}
detectorStopper := concurrency.NewStopper()
netFlowQueueSize := queueScaler.ScaleSizeOnNonDefault(env.DetectorNetworkFlowBufferSize)
```
You should apply the same pattern to all other required `Builder` fields that are not visible in this snippet (for example `clusterID`, `enforcer`, and the various stores). At the top of `Build`, add `nil` / empty checks for each such field and panic with a clear, actionable message (e.g. `"detector.Builder.Build: enforcer must be set; call WithEnforcer before Build"`). This keeps the `Build` signature unchanged while ensuring misconfiguration fails fast with an obvious error.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
📝 WalkthroughSummary by CodeRabbit
WalkthroughIntroduces a fluent Builder pattern for constructing Detector instances, replacing the monolithic Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@sensor/common/detector/builder.go`:
- Around line 119-191: Builder.Build currently constructs a detectorImpl without
validating required wiring, which can lead to nil dereferences at runtime; add
explicit nil checks at the start of Builder.Build for the required dependencies
(e.g., b.clusterLabelProvider, b.namespaceLabelProvider, b.imageCache,
b.serviceAccountStore, b.deploymentStore, b.nodeStore, b.enforcer,
b.admCtrlSettingsMgr, b.auditLogUpdater, b.networkPolicyStore and any other
fields you rely on inside detectorImpl or methods like
newEnricher/newDeduper/baseline.NewBaselineEvaluator), and if any are nil fail
fast (e.g., panic or log.Fatalf with a clear message naming Builder.Build and
the missing field) so mis-wired detectors are detected immediately; add/update
unit tests to assert that Build panics/errs when required fields are not
provided.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Central YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro
Run ID: 3eebce49-a6bf-4a00-a4d5-c0619932b164
📒 Files selected for processing (4)
sensor/common/detector/builder.gosensor/common/detector/detector.gosensor/common/detector/enricher.gosensor/kubernetes/sensor/sensor.go
💤 Files with no reviewable changes (1)
- sensor/common/detector/detector.go
The 14-parameter positional constructor was hard to read and extend. Replaced with a Builder struct and chained WithX() methods as described in the ticket. Exported the ClusterIDProvider interface (formerly clusterIDPeekWaiter) to support the exported Builder type. Build() validates that the 13 required dependencies are set, returning an error if any are missing. Only admCtrlSettingsMgr is optional (nil-guarded in the detector implementation). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8e5d6b2 to
3d2c9d8
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #19741 +/- ##
==========================================
- Coverage 49.59% 49.57% -0.02%
==========================================
Files 2756 2757 +1
Lines 207961 208107 +146
==========================================
+ Hits 103129 103177 +48
- Misses 97172 97268 +96
- Partials 7660 7662 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Description
The 14-parameter positional constructor was hard to read and extend. Replaced with a Builder struct and chained WithX() methods as described in the ticket. Exported the ClusterIDProvider interface (formerly clusterIDPeekWaiter) to support the exported Builder type.
There may be some more refactoring possible here - I thought perhaps creating a
StoreProviderinterface incommon/storeso that the builder can be simplified to acceptWithStoreProviderrather than many individualWithXStoremethods.User-facing documentation
Testing and quality
Automated testing
How I validated my change
This is a superficial refactor to ease code readability; build & unit tests are enough validation.