Skip to content

[CONTP-1606] [DDGR] Reduce boilerplate: CreateResult, stateful handlers, handler registry#2911

Merged
tbavelier merged 40 commits into
mainfrom
tbavelier/generic-resource-improvements-create-result
Apr 22, 2026
Merged

[CONTP-1606] [DDGR] Reduce boilerplate: CreateResult, stateful handlers, handler registry#2911
tbavelier merged 40 commits into
mainfrom
tbavelier/generic-resource-improvements-create-result

Conversation

@tbavelier

@tbavelier tbavelier commented Apr 16, 2026

Copy link
Copy Markdown
Member

What does this PR do?

1. Uniform createResourcefunc: return CreateResult instead of mutating status (48d50bc)

Makes createResourcefunc consistent with the other three ResourceHandler interface methods (get, update, delete).

Previously, createResourcefunc had a fat, inconsistent signature — it took ctx, status, now, and hash in addition to r and instance, and each of the 6 handler implementations owned error logging, updateErrStatus calls, and direct status mutation.

Introduces CreateResult{ID, CreatedTime, Creator} and reduces the interface method to:

createResourcefunc(r *Reconciler, instance *v1alpha1.DatadogGenericResource) (CreateResult, error)

All shared logic (error logging, updateErrStatus, populating Id/Created/LastForceSyncTime/Creator/SyncStatus/CurrentHash) is now consolidated in r.create.

2. Replace getHandler switch with handler registry map (ab2b909)

Replaces the switch statement and separate testHandlers map with a single handlers map. Adding a new resource type is now one map entry instead of a switch case.

3. Resolve handler once at Reconcile entry, remove wrapper layer (4d3de07)

Resolves the ResourceHandler once at the top of Reconcile and passes it through to create/update. Removes the apiGet/apiUpdate/apiDelete/apiCreateAndUpdateStatus one-liner wrapper functions and the r.get method. The handler is called directly at each call site.

4. Fix inconsistent json.Unmarshal error handling (c2f623e)

monitors.go, notebooks.go, and synthetics.go were silently ignoring json.Unmarshal errors, while dashboards.go and downtimes.go already checked them. Now all handlers surface invalid JSON specs as errors.

5. Make handlers stateful with own API clients (02c7d90)

Each ResourceHandler now holds its own auth context and typed API client (DashboardHandler{auth, client} instead of DashboardHandler{}), removing the coupling to the Reconciler struct. The Reconciler no longer carries 5 typed client fields — it holds a handlers map built by buildHandlers(). UpdateDatadogClient replaces the entire map on credential refresh.

The ResourceHandler interface methods drop the *Reconciler parameter and are renamed from createResourcefunc/getResourcefunc/etc to createResource/getResource/etc.

Motivation

  • Each handler was repeating the same error handling and status population boilerplate
  • Changing how errors are logged or how status fields are set required touching all 6 handler files
  • The inconsistency made the interface harder to understand and extend
  • The Reconciler struct was a bag of typed clients that every handler reached into — now each handler is self-contained

How to QA

Verify CRUD works: create a DDGR, update it, delete it, and verify at every step it's reflected in the UI

Checklist

  • PR has at least one valid label: bug, enhancement, refactoring, documentation, tooling, and/or dependencies
  • PR has a milestone or the qa/skip-qa label
  • All commits are signed (see: signing commits)

wdhif and others added 14 commits April 15, 2026 12:04
Signed-off-by: Wassim DHIF <[email protected]>
MockHandler and its state (mockGetErr, mockUpdateErr, etc.) lived in
utils.go but were only referenced from test files, causing golangci-lint
to flag them as unused (and the error vars as violating errname). Moved
all mock code to mock_handler_test.go and registered the handler via
init(), with a testHandlers map in utils.go as the bridge.
Signed-off-by: Wassim DHIF <[email protected]>
…/generic-resource-improvements-context-logging
@tbavelier tbavelier added this to the v1.27.0 milestone Apr 16, 2026
@tbavelier tbavelier added the enhancement New feature or request label Apr 16, 2026
@tbavelier tbavelier changed the title [DDGR] Uniform createResourcefunc: return CreateResult instead of mutating status [CONTP-1606] [DDGR] Uniform createResourcefunc: return CreateResult instead of mutating status Apr 16, 2026
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Apr 16, 2026

Copy link
Copy Markdown

Code Coverage

Fix all issues with BitsAI

🛑 Gate Violations

🎯 1 Code Coverage issue detected

A Patch coverage percentage gate may be blocking this PR.

Patch coverage: 36.00% (threshold: 80.00%)

ℹ️ Info

🎯 Code Coverage (details)
Patch Coverage: 36.00%
Overall Coverage: 40.14% (-0.06%)

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 7d596f5 | Docs | Datadog PR Page | Give us feedback!

@codecov-commenter

codecov-commenter commented Apr 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 32.46753% with 104 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.01%. Comparing base (6e2c0c9) to head (7d596f5).

Files with missing lines Patch % Lines
...al/controller/datadoggenericresource/synthetics.go 33.33% 28 Missing ⚠️
...nal/controller/datadoggenericresource/downtimes.go 0.00% 20 Missing ⚠️
...rnal/controller/datadoggenericresource/monitors.go 0.00% 18 Missing ⚠️
...nal/controller/datadoggenericresource/notebooks.go 0.00% 18 Missing ⚠️
...al/controller/datadoggenericresource/dashboards.go 0.00% 15 Missing ⚠️
...al/controller/datadoggenericresource/controller.go 83.87% 4 Missing and 1 partial ⚠️

❌ Your patch status has failed because the patch coverage (32.46%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2911      +/-   ##
==========================================
- Coverage   40.08%   40.01%   -0.08%     
==========================================
  Files         320      320              
  Lines       28075    28037      -38     
==========================================
- Hits        11254    11219      -35     
+ Misses      16012    16007       -5     
- Partials      809      811       +2     
Flag Coverage Δ
unittests 40.01% <32.46%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...nal/controller/datadoggenericresource/finalizer.go 64.28% <100.00%> (-20.33%) ⬇️
...nternal/controller/datadoggenericresource/utils.go 100.00% <100.00%> (+17.77%) ⬆️
...al/controller/datadoggenericresource/controller.go 65.11% <83.87%> (-0.21%) ⬇️
...al/controller/datadoggenericresource/dashboards.go 0.00% <0.00%> (-16.67%) ⬇️
...rnal/controller/datadoggenericresource/monitors.go 0.00% <0.00%> (ø)
...nal/controller/datadoggenericresource/notebooks.go 0.00% <0.00%> (-11.33%) ⬇️
...nal/controller/datadoggenericresource/downtimes.go 0.00% <0.00%> (ø)
...al/controller/datadoggenericresource/synthetics.go 16.47% <33.33%> (-10.34%) ⬇️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6e2c0c9...7d596f5. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tbavelier and others added 7 commits April 16, 2026 16:22
…/generic-resource-improvements-context-logging
…ating status

Each ResourceHandler implementation previously owned error logging,
status mutation (Id, Created, Creator, SyncStatus, CurrentHash), and
had a fat signature inconsistent with the other three interface methods.

Introduce CreateResult{ID, CreatedTime, Creator} and reduce
createResourcefunc to (r, instance) -> (CreateResult, error), matching
get/update/delete. All shared logic (error logging, updateErrStatus,
status population) is consolidated in apiCreateAndUpdateStatus.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@tbavelier
tbavelier force-pushed the tbavelier/generic-resource-improvements-create-result branch from e2e84bf to 48d50bc Compare April 17, 2026 08:34
tbavelier and others added 12 commits April 17, 2026 10:41
reconcile.AsReconciler already fetches the object before calling
Reconcile(ctx, instance). The previous implementation rebuilt a Request
and delegated to the internal Reconcile which performed a second Get,
resulting in two cache reads per reconcile loop.

Split internalReconcile into:
- Reconcile(ctx, req): keeps the Get for backward-compat/test use
- ReconcileInstance(ctx, instance): skips the Get, used by the outer
  controller which receives a pre-fetched object from AsReconciler

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…' into tbavelier/generic-resource-improvements-create-result
…' into tbavelier/generic-resource-improvements-create-result
Replace the switch statement and separate testHandlers map with a single
handlers map. Adding a new resource type is now one map entry instead of
a switch case. Tests register mocks directly into the same map.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Resolve the ResourceHandler once at the top of Reconcile and pass it
through to create/update. Inline the handler calls in the finalizer.
Remove the apiGet/apiUpdate/apiDelete/apiCreateAndUpdateStatus wrappers
that were one-liner indirections. Replace thin Test_api* tests with a
focused Test_getHandler that covers the registry lookup and panic path.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
monitors, notebooks, and synthetics were silently ignoring unmarshal
errors, while dashboards and downtimes already checked them. Now all
handlers surface invalid JSON specs as errors instead of sending
zero-value bodies to the API.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Each ResourceHandler now holds its own auth context and typed API
client, removing the coupling to the Reconciler struct. The Reconciler
no longer carries 5 typed client fields — it holds a handlers map built
by buildHandlers(). UpdateDatadogClient replaces the entire map on
credential refresh.

The ResourceHandler interface methods drop the *Reconciler parameter and
are renamed from createResourcefunc/getResourcefunc/etc to
createResource/getResource/etc.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@tbavelier tbavelier changed the title [CONTP-1606] [DDGR] Uniform createResourcefunc: return CreateResult instead of mutating status [CONTP-1606] [DDGR] Reduce boilerplate: CreateResult, stateful handlers, handler registry Apr 17, 2026
Base automatically changed from tbavelier/generic-resource-improvements-context-logging to main April 20, 2026 09:04
…te-result

# Conflicts:
#	internal/controller/datadoggenericresource/controller.go
#	internal/controller/datadoggenericresource/dashboards.go
#	internal/controller/datadoggenericresource/downtimes.go
#	internal/controller/datadoggenericresource/mock_handler_test.go
#	internal/controller/datadoggenericresource/monitors.go
#	internal/controller/datadoggenericresource/notebooks.go
#	internal/controller/datadoggenericresource/resource_handler.go
#	internal/controller/datadoggenericresource/synthetics.go
#	internal/controller/datadoggenericresource/synthetics_test.go
#	internal/controller/datadoggenericresource/utils.go
#	internal/controller/datadoggenericresource/utils_test.go
@tbavelier
tbavelier marked this pull request as ready for review April 20, 2026 15:37
@tbavelier
tbavelier requested a review from a team April 20, 2026 15:37
@tbavelier
tbavelier requested a review from a team as a code owner April 20, 2026 15:37
@tbavelier
tbavelier merged commit dcbf3bf into main Apr 22, 2026
37 of 38 checks passed
@tbavelier
tbavelier deleted the tbavelier/generic-resource-improvements-create-result branch April 22, 2026 06:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants