Skip to content

Conversation

@qiujian16
Copy link
Member

@qiujian16 qiujian16 commented Nov 10, 2025

We can leverage contextual logger in base controller.

Summary

Related issue(s)

Fixes #

Summary by CodeRabbit

  • New Features

    • Contextual, component-scoped event logging for clearer runtime diagnostics.
  • Refactor

    • Controllers moved to explicit key-based sync entry points and typed work queues for more predictable processing.
    • Event recorder package reorganized and usages standardized across runtime and tests.
  • Tests

    • Test scaffolding updated to align with new sync/key and typed-queue patterns.
  • Chores

    • SDK dependency bumped and several transitive dependencies removed.

@openshift-ci openshift-ci bot requested review from elgnay and xuezhaojun November 10, 2025 07:14
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 10, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: qiujian16

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai
Copy link

coderabbitai bot commented Nov 10, 2025

Walkthrough

Upgrades sdk-go and adjusts many controller/factory and queue APIs: renames common/helpers → common/recorder, adds a contextual logging recorder and fake SDK sync context, converts queue/key callbacks to return slices, updates numerous controller sync signatures and test helpers, and replaces several imports to sdk-go factory and cloudevents builder.

Changes

Cohort / File(s) Summary
Dependency updates
go.mod
Bumps open-cluster-management.io/sdk-go to v1.1.1-0.20251110055937-105041a1c094; removes several indirect transitive dependencies (docker/moby/winio/hcsshim/kafka-related).
Recorder package & new recorder
pkg/common/recorder/event_recorder.go, pkg/common/recorder/event_recorder_test.go, pkg/common/recorder/logging_recorder.go
Renames package helpersrecorder; adds ContextualLoggingEventRecorder and related constructors/methods; tests updated to use new package name.
Testing SDK sync context
pkg/common/testing/fake_sync_context.go
Adds FakeSDKSyncContext and NewFakeSDKSyncContext(t, clusterName) with a typed string queue and recorder.
Queue/Filter API changes
pkg/common/queue/queuekey.go, pkg/work/helper/helpers.go
FileterByLabel now returns func(obj interface{}) bool (instead of factory.EventFilterFunc); queue key callbacks changed from single string returns to []string (ObjectQueueKeyFunc → ObjectQueueKeysFunc).
Recorder import updates across repo
pkg/placement/..., pkg/registration/..., pkg/registration/spoke/spokeagent.go, ...
Replace imports from open-cluster-management.io/ocm/pkg/common/helpers to .../recorder and update NewEventRecorder call sites.
Controller factory migration & sync signature changes (hub & spoke)
many files under pkg/work/hub/controllers/..., pkg/work/spoke/controllers/... (e.g. .../manifestworkgarbagecollection/..., .../manifestworkreplicasetcontroller/..., .../finalizercontroller/..., .../manifestcontroller/..., .../statuscontroller/..., .../auth/...)
Replace github.com/openshift/library-go/.../factory with open-cluster-management.io/sdk-go/pkg/basecontroller/factory; remove recorder parameter from ToController(...); switch builder callbacks to ...QueueKeysFunc/typed queues; update many sync methods to accept an explicit key/name string (often adding or ignoring SyncContext).
Controller tests & queue typing updates
tests under pkg/work/..., pkg/registration/... (e.g. .../manifestwork_reconciler_test.go, .../manifestworkreplicaset_controllers_test.go, etc.)
Tests updated to use testingcommon.NewFakeSDKSyncContext, pass explicit key/name to sync calls, and replace untyped queues with workqueue.NewTypedRateLimitingQueue[string](...).
Cloudevents config loader changes
pkg/work/hub/manager.go, pkg/work/spoke/spokeagent.go, pkg/registration/register/grpc/spoke_driver.go
Replace generic.NewConfigLoader with genericbuilder.NewConfigLoader from open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder (aliasing).
Auth & logging adjustments
pkg/work/spoke/auth/*
Switch to contextual structured logging (klog.FromContext(ctx)), update NewSyncContext/ToController usages to new factory API, and change cache/controller sync signatures to accept an executor key string.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas to review closely:

  • Sync signature changes across many controllers and tests — ensure all call sites were updated and key/name semantics are consistent.
  • Queue callback conversions to []string — confirm empty vs single-element semantics and framework compatibility.
  • New ContextualLoggingEventRecorder and its usage — verify context propagation and that recorder behavior matches expectations.
  • Removal of recorder argument from ToController — ensure no remaining expectations for controller-provided recorder in affected code.

Possibly related PRs

Suggested labels

lgtm

Suggested reviewers

  • elgnay

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete; it contains only a brief summary line and template boilerplate with unfilled sections (Summary, Related issue). Critical details about the changes are missing. Complete the description by filling in the Summary section with details about leveraging contextual loggers and base controller integration, and reference any related issues.
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adopting the base controller from sdk-go, which is the primary objective reflected across all file modifications.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Nov 10, 2025

Codecov Report

❌ Patch coverage is 33.75000% with 53 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.14%. Comparing base (7eb4ff9) to head (f8cceaf).

Files with missing lines Patch % Lines
pkg/common/recorder/logging_recorder.go 0.00% 25 Missing ⚠️
pkg/work/helper/helpers.go 0.00% 4 Missing ⚠️
...setcontroller/manifestworkreplicaset_controller.go 42.85% 4 Missing ⚠️
...rs/finalizercontroller/add_finalizer_controller.go 0.00% 3 Missing ⚠️
...troller/appliedmanifestwork_finalize_controller.go 0.00% 3 Missing ⚠️
...ers/statuscontroller/availablestatus_controller.go 0.00% 3 Missing ⚠️
pkg/work/spoke/auth/factory.go 0.00% 2 Missing ⚠️
...izercontroller/manifestwork_finalize_controller.go 33.33% 2 Missing ⚠️
...roller/unmanaged_appliedmanifestwork_controller.go 33.33% 2 Missing ⚠️
...lers/manifestcontroller/manifestwork_controller.go 66.66% 2 Missing ⚠️
... and 3 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1251      +/-   ##
==========================================
- Coverage   62.22%   62.14%   -0.09%     
==========================================
  Files         209      210       +1     
  Lines       16997    17016      +19     
==========================================
- Hits        10576    10574       -2     
- Misses       5304     5325      +21     
  Partials     1117     1117              
Flag Coverage Δ
unit 62.14% <33.75%> (-0.09%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/common/queue/queuekey.go (1)

10-15: Fix return type inconsistency and correct the typo in function names.

The review comment is accurate. FileterByLabel returns func(obj interface{}) bool (untyped), while FileterByLabelKeyValue and FilterByNames return factory.EventFilterFunc (typed alias). Although factory.EventFilterFunc is defined as type EventFilterFunc func(obj interface{}) bool, the inconsistent return types should be unified for code consistency. Additionally, the typo "Fileter" appears in both line 10 and line 17 and should be corrected to "Filter" in the function names and all call sites.

Changes needed:

  • Rename FileterByLabelFilterByLabel
  • Rename FileterByLabelKeyValueFilterByLabelKeyValue
  • Change FileterByLabel return type from func(obj interface{}) bool to factory.EventFilterFunc
  • Update all call sites in test files and production code (5 usages identified)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7eb4ff9 and c0eb459.

⛔ Files ignored due to path filters (99)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/message.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/option.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/protocol.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/write_producer_message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/00version.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminapi.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminoptions.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/api.html is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_dynamic.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_windows.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/config.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/consumer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/context.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error_gen.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/event.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/generated_errors.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/glue_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/handle.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/header.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/kafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/LICENSES.txt is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/bundle-import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_windows.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka_mock.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/log.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/metadata.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/misc.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/mockcluster.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/offset.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/producer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/select_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/testconf-example.json is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/time.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/base_controller.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/addon/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/cluster/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/csr/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/event/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/lease/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/options/generic.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/store/informer.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/store/interface.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/store/simplestore.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/codec/manifestbundle.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/source/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/store/base.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/store/informer.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/store/local.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/constants/constants.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/agentclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/baseclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/sourceclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/interface.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/metrics/metrics_collector.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/cert/rotation.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/protocol/protocol.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options_noop.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/logger.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/utils/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/heartbeat/healthcheck.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/heartbeat/heartbeat.go is excluded by !vendor/**
📒 Files selected for processing (37)
  • go.mod (1 hunks)
  • pkg/common/queue/queuekey.go (1 hunks)
  • pkg/common/recorder/event_recorder.go (1 hunks)
  • pkg/common/recorder/event_recorder_test.go (1 hunks)
  • pkg/common/recorder/logging_recorder.go (1 hunks)
  • pkg/common/testing/fake_sync_context.go (1 hunks)
  • pkg/placement/controllers/manager.go (2 hunks)
  • pkg/registration/hub/lease/controller_test.go (3 hunks)
  • pkg/registration/hub/manager.go (1 hunks)
  • pkg/registration/register/grpc/spoke_driver.go (3 hunks)
  • pkg/registration/spoke/managedcluster/claim_reconcile_test.go (3 hunks)
  • pkg/registration/spoke/managedcluster/joining_controller_test.go (2 hunks)
  • pkg/registration/spoke/managedcluster/resource_reconcile_test.go (2 hunks)
  • pkg/registration/spoke/spokeagent.go (2 hunks)
  • pkg/work/helper/helpers.go (2 hunks)
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go (2 hunks)
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go (1 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go (3 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go (1 hunks)
  • pkg/work/hub/manager.go (2 hunks)
  • pkg/work/spoke/auth/cache/auth.go (1 hunks)
  • pkg/work/spoke/auth/cache/executor_cache_controller.go (6 hunks)
  • pkg/work/spoke/auth/factory.go (1 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go (1 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go (1 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go (1 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go (2 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go (2 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go (5 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go (3 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go (6 hunks)
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go (2 hunks)
  • pkg/work/spoke/spokeagent.go (2 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1086
File: test/integration/util/grpc.go:146-146
Timestamp: 2025-07-23T10:10:42.066Z
Learning: In OCM codebase, there are two different GRPCServerOptions types: the local one in pkg/server/grpc/options.go (which only has GRPCServerConfig field) and the SDK one from open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/options (which has ServerBindPort and other fields with default values). Test code uses the SDK version via grpcoptions import alias.
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1196
File: pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go:231-242
Timestamp: 2025-10-14T09:37:12.472Z
Learning: In the ocm repository, there are two different factory packages with different SyncContext.Queue() return types:
1. `github.com/openshift/library-go/pkg/controller/factory` returns `workqueue.RateLimitingInterface` (non-typed)
2. `open-cluster-management.io/sdk-go/pkg/basecontroller/factory` returns `workqueue.TypedRateLimitingInterface[string]` (typed)

When reviewing controller code, check which factory import is used to determine the correct queue interface type.
📚 Learning: 2025-07-23T10:10:42.066Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1086
File: test/integration/util/grpc.go:146-146
Timestamp: 2025-07-23T10:10:42.066Z
Learning: In OCM codebase, there are two different GRPCServerOptions types: the local one in pkg/server/grpc/options.go (which only has GRPCServerConfig field) and the SDK one from open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/options (which has ServerBindPort and other fields with default values). Test code uses the SDK version via grpcoptions import alias.

Applied to files:

  • pkg/registration/hub/lease/controller_test.go
  • pkg/registration/spoke/managedcluster/joining_controller_test.go
  • pkg/work/spoke/spokeagent.go
  • pkg/registration/spoke/managedcluster/claim_reconcile_test.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go
  • pkg/registration/spoke/managedcluster/resource_reconcile_test.go
  • pkg/registration/register/grpc/spoke_driver.go
  • pkg/registration/spoke/spokeagent.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go
  • pkg/work/helper/helpers.go
  • pkg/work/hub/manager.go
  • pkg/placement/controllers/manager.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
📚 Learning: 2025-10-14T09:37:12.472Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1196
File: pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go:231-242
Timestamp: 2025-10-14T09:37:12.472Z
Learning: In the ocm repository, there are two different factory packages with different SyncContext.Queue() return types:
1. `github.com/openshift/library-go/pkg/controller/factory` returns `workqueue.RateLimitingInterface` (non-typed)
2. `open-cluster-management.io/sdk-go/pkg/basecontroller/factory` returns `workqueue.TypedRateLimitingInterface[string]` (typed)

When reviewing controller code, check which factory import is used to determine the correct queue interface type.

Applied to files:

  • pkg/common/testing/fake_sync_context.go
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go
  • pkg/work/spoke/auth/cache/auth.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go
  • pkg/work/helper/helpers.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
📚 Learning: 2025-11-06T08:55:13.306Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1242
File: pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go:88-88
Timestamp: 2025-11-06T08:55:13.306Z
Learning: In pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go, the sync method initializes a logger with manifestWorkName and attaches it to the context before calling reconcile methods. Therefore, reconcile methods (like manifestworkReconciler.reconcile) that use klog.FromContext(ctx) automatically inherit the manifestWorkName context and do not need to add it again.

Applied to files:

  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go
  • pkg/work/spoke/auth/factory.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
📚 Learning: 2025-07-15T06:10:13.001Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1071
File: pkg/server/grpc/clients.go:73-76
Timestamp: 2025-07-15T06:10:13.001Z
Learning: In OCM (Open Cluster Management) gRPC server informer setup, cache sync verification is not necessary when starting informers in the clients.Run() method. The current pattern of starting informers as goroutines without explicit cache sync waiting is the preferred approach for this codebase.

Applied to files:

  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go
  • pkg/registration/spoke/managedcluster/joining_controller_test.go
  • pkg/registration/spoke/managedcluster/resource_reconcile_test.go
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go
  • pkg/registration/spoke/spokeagent.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go
  • pkg/placement/controllers/manager.go
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
📚 Learning: 2025-10-28T02:55:13.893Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1224
File: pkg/registration/register/grpc/spoke_driver.go:89-98
Timestamp: 2025-10-28T02:55:13.893Z
Learning: In pkg/registration/register/grpc/spoke_driver.go (Go), when calling cloudeventscsr.NewAgentClientHolder with GenericClientOptions, the watcher store does not need to be explicitly provided via WithClientWatcherStore. The GenericClientOptions.AgentClient() method automatically creates a default AgentInformerWatcherStore if none is provided, which satisfies the NewAgentClientHolder requirements.

Applied to files:

  • pkg/work/spoke/spokeagent.go
  • pkg/registration/register/grpc/spoke_driver.go
  • pkg/registration/spoke/spokeagent.go
  • pkg/work/hub/manager.go
  • pkg/placement/controllers/manager.go
📚 Learning: 2025-06-26T00:34:09.815Z
Learnt from: zhiweiyin318
Repo: open-cluster-management-io/ocm PR: 1046
File: manifests/cluster-manager/hub/cluster-manager-clusterprofiles-clusterrole.yaml:5-10
Timestamp: 2025-06-26T00:34:09.815Z
Learning: The open-cluster-management-io/ocm codebase uses Go templates (text/template), not Helm templates. The standard pattern for dynamic labels in manifests is: `{{ if gt (len .Labels) 0 }}{{ range $key, $value := .Labels }}"{{ $key }}": "{{ $value }}"{{ end }}{{ end }}`. Do not suggest Helm-specific functions like `toYaml` for this codebase.

Applied to files:

  • pkg/registration/spoke/managedcluster/claim_reconcile_test.go
📚 Learning: 2025-09-03T08:43:34.751Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1158
File: test/integration/work/completedmanifestwork_test.go:216-256
Timestamp: 2025-09-03T08:43:34.751Z
Learning: In TTL=0 ManifestWork deletion tests, avoid waiting for WorkComplete condition because the controller deletes the resource immediately upon completion, creating a race condition where the test tries to check completion status on an already-deleted resource.

Applied to files:

  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go
📚 Learning: 2025-08-04T08:58:41.865Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1107
File: manifests/klusterlet/management/klusterlet-registration-deployment.yaml:111-115
Timestamp: 2025-08-04T08:58:41.865Z
Learning: In OCM klusterlet deployments, gRPC authentication uses different file naming conventions than CSR/kube authentication: gRPC auth expects config.yaml files (/spoke/bootstrap/config.yaml and /spoke/hub-kubeconfig/config.yaml) while CSR/kube auth uses kubeconfig files. The gRPC driver explicitly creates config.yaml files in the secret data via additionalSecretData["config.yaml"] = d.configTemplate.

Applied to files:

  • pkg/registration/register/grpc/spoke_driver.go
📚 Learning: 2025-09-24T00:18:33.339Z
Learnt from: zhiweiyin318
Repo: open-cluster-management-io/ocm PR: 1194
File: deploy/klusterlet/chart/klusterlet/templates/bootstrap_kubeconfig_secret.yaml:25-27
Timestamp: 2025-09-24T00:18:33.339Z
Learning: gRPC config in OCM klusterlet bootstrap secrets does not support multiHubBootstrapHubKubeConfigs scenarios - it is intentionally designed only for single hub bootstrap configurations.

Applied to files:

  • pkg/registration/register/grpc/spoke_driver.go
📚 Learning: 2025-07-02T05:42:41.749Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1058
File: pkg/server/services/work/work.go:39-49
Timestamp: 2025-07-02T05:42:41.749Z
Learning: In the OCM (Open Cluster Management) codebase, nil checks with panic statements in constructor functions for interface parameters are considered unnecessary, as the dependency injection/wiring is managed properly and such checks are not part of the established codebase patterns.

Applied to files:

  • pkg/placement/controllers/manager.go
🧬 Code graph analysis (28)
pkg/registration/hub/lease/controller_test.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/common/testing/fake_sync_context.go (1)
vendor/open-cluster-management.io/addon-framework/pkg/addonmanager/addontesting/helpers.go (1)
  • NewTestingEventRecorder (318-320)
pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go (2)
pkg/work/helper/helpers.go (2)
  • AppliedManifestworkQueueKeyFunc (301-310)
  • AppliedManifestworkHubHashFilter (324-329)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/registration/spoke/managedcluster/joining_controller_test.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/work/spoke/spokeagent.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
pkg/registration/spoke/managedcluster/claim_reconcile_test.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/registration/spoke/managedcluster/resource_reconcile_test.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/registration/register/grpc/spoke_driver.go (3)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/constants/constants.go (1)
  • ConfigTypeGRPC (5-5)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/options.go (1)
  • LoadConfig (158-174)
pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/registration/spoke/spokeagent.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go (1)
pkg/common/recorder/logging_recorder.go (1)
  • NewContextualLoggingEventRecorder (23-27)
pkg/work/hub/manager.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go (3)
pkg/common/queue/queuekey.go (1)
  • QueueKeyByMetaName (57-60)
pkg/work/helper/helpers.go (1)
  • AppliedManifestworkAgentIDFilter (313-321)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go (2)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/controller_context.go (1)
  • NewSyncContext (21-28)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/placement/controllers/manager.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go (2)
pkg/common/queue/queuekey.go (1)
  • FileterByLabel (10-15)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/spoke/auth/cache/executor_cache_controller.go (3)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/controller_context.go (1)
  • NewSyncContext (21-28)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/auth/store/cache_store.go (1)
  • Dimension (75-82)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: unit
  • GitHub Check: e2e-singleton
  • GitHub Check: e2e-hosted
  • GitHub Check: integration
  • GitHub Check: verify
  • GitHub Check: e2e
  • GitHub Check: build
  • GitHub Check: cloudevents-integration
🔇 Additional comments (53)
pkg/work/hub/manager.go (1)

21-21: LGTM! Improved readability with more descriptive import alias.

The rename from generic to genericbuilder makes the code more self-documenting, and the usage is updated consistently.

Also applies to: 80-80

pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go (3)

24-24: LGTM! Correct factory import for sdk-go migration.

The import has been properly updated to use the sdk-go basecontroller factory, which is consistent with the PR objectives.


79-81: LGTM! Clean migration to sdk-go controller construction.

The controller construction has been properly updated:

  • The recorder argument is correctly removed from ToController(), aligning with the sdk-go's contextual logging approach
  • The factory builder pattern is cleanly applied

84-107: LGTM! Excellent sync method migration.

The sync method has been properly updated to work with the sdk-go basecontroller:

  • The signature now includes manifestWorkName string as a parameter, which is the standard pattern for sdk-go basecontroller where the queue key is directly passed to the sync function
  • Logger initialization correctly uses the manifestWorkName parameter and attaches it to the context (line 85-87)
  • The typed queue usage at line 105 (Queue().AddAfter(manifestWorkName, ...)) is correct, as the sdk-go factory returns TypedRateLimitingInterface[string]

Based on learnings.

pkg/common/recorder/event_recorder_test.go (1)

1-1: LGTM! Package rename aligns with directory structure.

The package rename from helpers to recorder is consistent with the file's location in pkg/common/recorder/ and aligns with the broader refactoring to consolidate event recorder functionality.

pkg/work/spoke/auth/cache/auth.go (1)

20-20: LGTM! Clean migration to sdk-go base controller factory.

The import change from openshift/library-go to open-cluster-management.io/sdk-go/pkg/basecontroller/factory aligns with the PR's objective to leverage the base controller in sdk-go.

Based on learnings

pkg/work/spoke/auth/factory.go (1)

58-59: LGTM! Contextual logging improves observability.

The migration from klog.Infof to contextual logging with structured key-value pairs (logger.Info("Executor caches enabled", "cacheValidator", isCacheValidator)) aligns with the project-wide adoption of context-aware logging and improves log filtering and analysis.

go.mod (1)

44-44: LGTM! SDK upgrade enables new controller features.

The upgrade to open-cluster-management.io/sdk-go v1.1.1-0.20251110055937-105041a1c094 enables the base controller and contextual logging features used throughout this PR. Note that this is a pre-release version (indicated by the commit hash suffix).

pkg/work/helper/helpers.go (2)

32-32: LGTM! Import addition supports typed queue migration.

The addition of the sdk-go basecontroller/factory import enables the use of factory.ObjectQueueKeysFunc for multi-key queue operations.

Based on learnings


301-309: LGTM! Function signature updated for multi-key queue support.

The function signature change from factory.ObjectQueueKeyFunc returning string to factory.ObjectQueueKeysFunc returning []string aligns with the sdk-go base controller's typed queue interface. The implementation correctly wraps return values in slices:

  • Empty slice []string{} when the name doesn't match the hubhash prefix
  • Single-element slice []string{trimmedName} when it matches

Based on learnings

pkg/common/testing/fake_sync_context.go (1)

29-43: LGTM! Test helper added for SDK-based controllers.

The new FakeSDKSyncContext type provides test scaffolding for controllers migrated to the sdk-go base controller factory, using TypedRateLimitingInterface[string] consistent with the SDK's typed queue interface. The implementation mirrors the existing FakeSyncContext pattern while supporting the new typed queue.

Based on learnings

pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go (3)

20-20: LGTM! Migration to sdk-go base controller factory.

The import change from openshift/library-go to open-cluster-management.io/sdk-go/pkg/basecontroller/factory is consistent with the PR's objective to leverage the base controller in sdk-go.

Based on learnings


48-48: LGTM! ToController simplified with recorder removal.

The ToController call no longer passes the recorder argument, which aligns with the sdk-go base controller pattern where the recorder is likely managed internally by the factory.


52-54: LGTM! Sync method signature updated for SDK pattern.

The sync method signature change to accept a key string parameter aligns with the sdk-go base controller's sync interface. The key is now provided as a parameter rather than being derived from controllerContext.QueueKey(), consistent with the SDK's SyncContext interface that only provides Queue() access.

Based on learnings

pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go (1)

92-93: LGTM! SDK sync context migration is correct.

The test correctly migrates to NewFakeSDKSyncContext and passes the appropriate key parameter to the sync method, aligning with the SDK-based controller factory pattern.

pkg/work/spoke/auth/cache/executor_cache_controller.go (6)

20-20: LGTM! Factory import updated to SDK-based controller.

The migration from library-go/pkg/controller/factory to sdk-go/pkg/basecontroller/factory aligns with the PR objectives and the learned pattern about typed queue interfaces.

Based on learnings


111-111: LGTM! SDK sync context creation updated correctly.

The NewSyncContext call correctly removes the recorder parameter, matching the SDK factory API signature shown in the relevant code snippets.


140-140: LGTM! Controller builder updated to SDK pattern.

The ToController call correctly removes the recorder parameter, consistent with the SDK-based factory API.


257-260: LGTM! Excellent contextual logging implementation.

The sync method properly:

  • Accepts the executorKey parameter (aligning with SDK factory sync signature)
  • Extracts logger from context
  • Enriches logger with executorKey structured field
  • Re-attaches enriched logger to context for downstream use

This follows best practices for contextual logging.


263-265: LGTM! Structured logging migration is well done.

The conversion from klog.V(4).Infof to logger.V(4).Info with structured key-value pairs ("count", c.executorCaches.Count()) improves log machine-readability and follows modern logging best practices.


281-293: LGTM! Nested logger usage is correct.

The iterateCacheItemsFn properly extracts the logger from the already-enriched context and uses structured logging for the cache update operation.

pkg/registration/hub/lease/controller_test.go (3)

25-25: LGTM! Event recorder import path updated.

The import change from helpers to recorder is part of the systematic package reorganization moving event recording utilities to a dedicated package.


177-177: LGTM! Event recorder constructor updated.

The call site correctly uses recorder.NewEventRecorder matching the new package structure.


291-291: LGTM! Event recorder constructor updated.

Consistent usage of recorder.NewEventRecorder as expected.

pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go (1)

197-197: LGTM! Test migrated to SDK sync context.

The update to NewFakeSDKSyncContext is consistent with the broader test infrastructure migration to SDK-based patterns.

pkg/registration/spoke/managedcluster/resource_reconcile_test.go (2)

29-29: LGTM! Event recorder import updated.

Consistent with the project-wide migration to the recorder package.


323-323: LGTM! Event recorder constructor updated.

Correct usage of recorder.NewEventRecorder.

pkg/registration/spoke/managedcluster/joining_controller_test.go (2)

23-23: LGTM! Event recorder import updated.

Consistent with the package reorganization.


89-89: LGTM! Event recorder constructor updated.

Correct usage of recorder.NewEventRecorder.

pkg/registration/spoke/managedcluster/claim_reconcile_test.go (3)

28-28: LGTM! Event recorder import updated.

Consistent with the package reorganization.


202-202: LGTM! Event recorder constructor updated.

Correct usage of recorder.NewEventRecorder.


581-581: LGTM! Event recorder constructor updated.

Consistent usage in the second test case.

pkg/registration/spoke/spokeagent.go (2)

31-31: LGTM! Event recorder import updated with clear alias.

The import alias eventrecorder distinguishes the package from the events.Recorder interface type used throughout this file, improving code clarity.


361-361: LGTM! Event recorder constructor updated.

Correct usage of eventrecorder.NewEventRecorder with the aliased import.

pkg/registration/hub/manager.go (1)

32-32: LGTM!

The import path update from helpers to recorder is clean and maintains backward compatibility through the alias.

pkg/common/recorder/event_recorder.go (1)

1-1: LGTM!

Package rename from helpers to recorder clearly reflects the module's purpose for event recording.

pkg/work/spoke/spokeagent.go (1)

26-26: LGTM!

The migration from generic.NewConfigLoader to genericbuilder.NewConfigLoader correctly adopts the updated sdk-go API. The builder pattern provides better separation of concerns for configuration loading.

Also applies to: 237-237

pkg/registration/register/grpc/spoke_driver.go (1)

34-34: LGTM!

Consistent application of the genericbuilder.NewConfigLoader API in both bootstrapped and non-bootstrapped config loading paths.

Also applies to: 240-240, 249-249

pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go (2)

19-19: LGTM!

The migration from library-go factory to SDK basecontroller factory is correctly implemented. The switch from WithFilteredEventsInformersQueueKeyFunc (singular) to WithFilteredEventsInformersQueueKeysFunc (plural) aligns with the helper function returning []string, and the removal of the recorder from ToController is consistent with the new SDK API. Based on learnings.

Also applies to: 61-65


68-68: LGTM!

The sync method signature correctly adds the manifestWorkName parameter, which is now passed explicitly rather than being derived from the queue key within the method. This change aligns with the SDK basecontroller factory's typed queue interface. Based on learnings.

pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go (1)

289-290: LGTM!

Test correctly updated to use NewFakeSDKSyncContext and pass the appliedManifestWorkName parameter to the sync method, aligning with the controller's new signature.

pkg/placement/controllers/manager.go (1)

17-17: LGTM!

The import path and function call correctly updated to use the recorder package instead of helpers.

Also applies to: 47-47

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go (1)

248-249: LGTM!

Test correctly migrated to NewFakeSDKSyncContext and the sync method invocation properly includes the key parameter (namespace/name), consistent with the SDK basecontroller factory pattern.

pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go (2)

19-19: LGTM! Factory migration is consistent.

The migration from library-go factory to sdk-go basecontroller factory is correctly implemented. The removal of the recorder parameter from ToController aligns with the new SDK pattern where contextual logging is handled differently.

Also applies to: 59-59


62-65: LGTM! Sync signature and logging pattern are correct.

The updated signature accepts the appliedManifestWorkName as an explicit parameter, which aligns with the new SDK factory pattern. The logger construction correctly adds the work name to the context before propagating it to downstream operations.

Based on learnings

pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go (1)

207-208: LGTM! Test updates align with production changes.

The test correctly uses NewFakeSDKSyncContext and passes the work name as the third argument to sync, matching the updated controller signature.

pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go (2)

378-379: LGTM! Test sync calls correctly updated.

All test cases have been properly updated to use NewFakeSDKSyncContext and pass the work name as the third argument to sync, consistent with the new controller signature.

Also applies to: 421-422, 556-557, 593-594


900-900: LGTM! Queue construction updated to typed interface.

The queue construction correctly uses workqueue.NewTypedRateLimitingQueue[string] with DefaultTypedControllerRateLimiter[string](), aligning with the new SDK factory's typed queue interface.

Based on learnings

Also applies to: 1063-1063

pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go (1)

19-19: LGTM! Import and unused parameter handling are appropriate.

The factory import migration is correct, and marking the SyncContext parameter as unused with _ is the proper Go idiom since this reconciler doesn't reference it in its implementation.

Also applies to: 32-32

pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go (1)

22-22: LGTM! Test infrastructure correctly migrated.

The test properly imports the SDK factory, uses NewFakeSDKSyncContext, and passes the work name to sync, aligning with the production code changes.

Also applies to: 300-301

pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go (3)

28-28: LGTM! Controller factory migration is well-executed.

The migration to SDK factory is correctly implemented:

  • Import changed to sdk-go/pkg/basecontroller/factory
  • Sync context created using factory.NewSyncContext
  • ToController call properly removes the recorder parameter

Also applies to: 80-80, 120-120


126-129: LGTM! Sync signature and logging are correctly updated.

The sync method now receives manifestWorkName as an explicit string parameter, and the logger is initialized with this value before being attached to the context. This follows the established pattern for contextual logging in this codebase.

Based on learnings


231-242: LGTM! Event handlers correctly use typed queues.

Both onAddFunc and onUpdateFunc have been properly updated to accept workqueue.TypedRateLimitingInterface[string] instead of the non-typed interface, which aligns with the SDK factory's typed queue implementation.

Based on learnings

Also applies to: 244-267

We can leverage contextual logger in base controller.

Signed-off-by: Jian Qiu <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
pkg/work/spoke/auth/cache/executor_cache_controller.go (1)

261-261: Consider using a named constant for the cleanup trigger.

The magic string "key" is used as a special sentinel value to trigger cache cleanup during resync. This makes the code less clear and maintainable.

Consider defining a named constant at package level:

+const (
+	cleanupTriggerKey = "key"
+)
+
 var (
 	ResyncInterval = 10 * time.Minute
 )

Then use it in the check:

-	if executorKey == "key" {
+	if executorKey == cleanupTriggerKey {
pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go (1)

54-82: Clarify the unused recorder argument.

recorder is no longer passed to the sdk-go factory or stored on the controller, so callers now supply a value that is silently dropped. Please either remove the parameter (and adjust call sites) or plumb it into the new base controller so event recording continues to flow through the sync context. Leaving a dead parameter invites confusion later.

pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go (1)

66-122: Reconnect or drop the unused recorder parameter.

After the move to the sdk-go factory, recorder never gets used: it isn’t stored on ManifestWorkController, fed into the sync context, or otherwise propagated. Please either thread it into the new factory wiring (if events are still needed) or delete the parameter and clean up call sites. Carrying an unused constructor argument is misleading for future readers.

pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go (1)

29-46: Handle the recorder parameter explicitly.

recorder isn’t used anymore—ToController is invoked without it and the struct doesn’t retain it—so the argument is effectively ignored. Please remove the parameter or wire it into the new sdk-go factory so it serves a purpose. Otherwise we leave a misleading API.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0eb459 and f8cceaf.

⛔ Files ignored due to path filters (99)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/message.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/option.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/protocol.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/write_producer_message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/00version.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminapi.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminoptions.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/api.html is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_dynamic.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_windows.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/config.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/consumer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/context.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error_gen.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/event.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/generated_errors.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/glue_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/handle.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/header.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/kafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/LICENSES.txt is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/bundle-import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_windows.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka_mock.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/log.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/metadata.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/misc.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/mockcluster.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/offset.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/producer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/select_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/testconf-example.json is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/time.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/base_controller.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/addon/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/cluster/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/csr/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/event/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/lease/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/options/generic.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/store/informer.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/store/interface.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/store/simplestore.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/codec/manifestbundle.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/source/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/store/base.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/store/informer.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/store/local.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/constants/constants.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/agentclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/baseclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/sourceclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/interface.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/metrics/metrics_collector.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/cert/rotation.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/protocol/protocol.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options_noop.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/logger.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/utils/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/heartbeat/healthcheck.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/heartbeat/heartbeat.go is excluded by !vendor/**
📒 Files selected for processing (37)
  • go.mod (1 hunks)
  • pkg/common/queue/queuekey.go (1 hunks)
  • pkg/common/recorder/event_recorder.go (1 hunks)
  • pkg/common/recorder/event_recorder_test.go (1 hunks)
  • pkg/common/recorder/logging_recorder.go (1 hunks)
  • pkg/common/testing/fake_sync_context.go (1 hunks)
  • pkg/placement/controllers/manager.go (2 hunks)
  • pkg/registration/hub/lease/controller_test.go (3 hunks)
  • pkg/registration/hub/manager.go (1 hunks)
  • pkg/registration/register/grpc/spoke_driver.go (3 hunks)
  • pkg/registration/spoke/managedcluster/claim_reconcile_test.go (3 hunks)
  • pkg/registration/spoke/managedcluster/joining_controller_test.go (2 hunks)
  • pkg/registration/spoke/managedcluster/resource_reconcile_test.go (2 hunks)
  • pkg/registration/spoke/spokeagent.go (2 hunks)
  • pkg/work/helper/helpers.go (2 hunks)
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go (2 hunks)
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go (1 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go (3 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go (1 hunks)
  • pkg/work/hub/manager.go (2 hunks)
  • pkg/work/spoke/auth/cache/auth.go (1 hunks)
  • pkg/work/spoke/auth/cache/executor_cache_controller.go (6 hunks)
  • pkg/work/spoke/auth/factory.go (1 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go (1 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go (1 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go (2 hunks)
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go (1 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go (2 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go (2 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go (5 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go (3 hunks)
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go (6 hunks)
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go (2 hunks)
  • pkg/work/spoke/spokeagent.go (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • pkg/common/recorder/event_recorder_test.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • pkg/registration/spoke/managedcluster/claim_reconcile_test.go
  • pkg/registration/hub/manager.go
  • pkg/registration/hub/lease/controller_test.go
  • pkg/registration/spoke/spokeagent.go
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller_test.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go
  • pkg/registration/register/grpc/spoke_driver.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller_test.go
  • pkg/placement/controllers/manager.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller_test.go
  • pkg/common/recorder/event_recorder.go
  • go.mod
  • pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1196
File: pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go:231-242
Timestamp: 2025-10-14T09:37:12.472Z
Learning: In the ocm repository, there are two different factory packages with different SyncContext.Queue() return types:
1. `github.com/openshift/library-go/pkg/controller/factory` returns `workqueue.RateLimitingInterface` (non-typed)
2. `open-cluster-management.io/sdk-go/pkg/basecontroller/factory` returns `workqueue.TypedRateLimitingInterface[string]` (typed)

When reviewing controller code, check which factory import is used to determine the correct queue interface type.
📚 Learning: 2025-11-06T08:55:13.306Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1242
File: pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go:88-88
Timestamp: 2025-11-06T08:55:13.306Z
Learning: In pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go, the sync method initializes a logger with manifestWorkName and attaches it to the context before calling reconcile methods. Therefore, reconcile methods (like manifestworkReconciler.reconcile) that use klog.FromContext(ctx) automatically inherit the manifestWorkName context and do not need to add it again.

Applied to files:

  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
  • pkg/work/spoke/auth/factory.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go
📚 Learning: 2025-10-14T09:37:12.472Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1196
File: pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go:231-242
Timestamp: 2025-10-14T09:37:12.472Z
Learning: In the ocm repository, there are two different factory packages with different SyncContext.Queue() return types:
1. `github.com/openshift/library-go/pkg/controller/factory` returns `workqueue.RateLimitingInterface` (non-typed)
2. `open-cluster-management.io/sdk-go/pkg/basecontroller/factory` returns `workqueue.TypedRateLimitingInterface[string]` (typed)

When reviewing controller code, check which factory import is used to determine the correct queue interface type.

Applied to files:

  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go
  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go
  • pkg/common/testing/fake_sync_context.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go
  • pkg/work/helper/helpers.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go
  • pkg/work/spoke/auth/cache/auth.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go
📚 Learning: 2025-07-15T06:10:13.001Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1071
File: pkg/server/grpc/clients.go:73-76
Timestamp: 2025-07-15T06:10:13.001Z
Learning: In OCM (Open Cluster Management) gRPC server informer setup, cache sync verification is not necessary when starting informers in the clients.Run() method. The current pattern of starting informers as goroutines without explicit cache sync waiting is the preferred approach for this codebase.

Applied to files:

  • pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go
  • pkg/registration/spoke/managedcluster/resource_reconcile_test.go
  • pkg/registration/spoke/managedcluster/joining_controller_test.go
  • pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go
  • pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
  • pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go
📚 Learning: 2025-07-23T10:10:42.066Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1086
File: test/integration/util/grpc.go:146-146
Timestamp: 2025-07-23T10:10:42.066Z
Learning: In OCM codebase, there are two different GRPCServerOptions types: the local one in pkg/server/grpc/options.go (which only has GRPCServerConfig field) and the SDK one from open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/options (which has ServerBindPort and other fields with default values). Test code uses the SDK version via grpcoptions import alias.

Applied to files:

  • pkg/registration/spoke/managedcluster/resource_reconcile_test.go
  • pkg/registration/spoke/managedcluster/joining_controller_test.go
  • pkg/work/spoke/spokeagent.go
  • pkg/work/hub/manager.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go
  • pkg/work/helper/helpers.go
  • pkg/work/spoke/auth/cache/executor_cache_controller.go
  • pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go
📚 Learning: 2025-10-28T02:55:13.893Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1224
File: pkg/registration/register/grpc/spoke_driver.go:89-98
Timestamp: 2025-10-28T02:55:13.893Z
Learning: In pkg/registration/register/grpc/spoke_driver.go (Go), when calling cloudeventscsr.NewAgentClientHolder with GenericClientOptions, the watcher store does not need to be explicitly provided via WithClientWatcherStore. The GenericClientOptions.AgentClient() method automatically creates a default AgentInformerWatcherStore if none is provided, which satisfies the NewAgentClientHolder requirements.

Applied to files:

  • pkg/work/spoke/spokeagent.go
  • pkg/work/hub/manager.go
🧬 Code graph analysis (18)
pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/common/testing/fake_sync_context.go (1)
vendor/open-cluster-management.io/addon-framework/pkg/addonmanager/addontesting/helpers.go (1)
  • NewTestingEventRecorder (318-320)
pkg/registration/spoke/managedcluster/resource_reconcile_test.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/registration/spoke/managedcluster/joining_controller_test.go (1)
pkg/common/recorder/event_recorder.go (1)
  • NewEventRecorder (12-22)
pkg/work/spoke/spokeagent.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/hub/manager.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go (1)
pkg/common/testing/fake_sync_context.go (1)
  • NewFakeSDKSyncContext (37-43)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go (2)
pkg/common/queue/queuekey.go (1)
  • FileterByLabel (10-15)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go (3)
pkg/common/queue/queuekey.go (1)
  • QueueKeyByMetaName (57-60)
pkg/work/helper/helpers.go (1)
  • AppliedManifestworkAgentIDFilter (313-321)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/controllers/finalizercontroller/add_finalizer_controller.go (2)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go (1)
  • WithValues (35-52)
pkg/work/spoke/controllers/manifestcontroller/manifestwork_controller.go (3)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/controller_context.go (1)
  • NewSyncContext (21-28)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go (1)
  • WithValues (35-52)
pkg/work/spoke/auth/cache/executor_cache_controller.go (3)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/controller_context.go (1)
  • NewSyncContext (21-28)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/auth/store/cache_store.go (1)
  • Dimension (75-82)
pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
pkg/work/spoke/controllers/statuscontroller/availablestatus_controller.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/basecontroller/factory/interfaces.go (1)
  • SyncContext (33-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: cloudevents-integration
  • GitHub Check: verify
  • GitHub Check: integration
  • GitHub Check: unit
  • GitHub Check: e2e-singleton
  • GitHub Check: e2e-hosted
  • GitHub Check: e2e
🔇 Additional comments (33)
pkg/work/spoke/auth/factory.go (1)

58-59: LGTM! Clean adoption of contextual, structured logging.

The change from plain klog.Infof to context-derived structured logging is a solid improvement. The key-value format is more maintainable and the contextual logger can carry request-specific metadata.

pkg/registration/spoke/managedcluster/joining_controller_test.go (2)

23-23: LGTM! Package import updated correctly.

The import change from helpers to recorder aligns with the broader refactor to consolidate event recording utilities. Based on learnings.


89-93: LGTM! Event recorder creation updated correctly.

The call to recorder.NewEventRecorder is correct with all required parameters properly supplied, and error handling is appropriately implemented. This change enables contextual logging support in the test.

pkg/work/hub/manager.go (1)

21-21: LGTM! Improved import alias naming.

The import alias rename from generic to genericbuilder improves code clarity by making the package purpose more explicit. The usage is consistently updated throughout the file.

Also applies to: 80-80

pkg/work/spoke/auth/cache/auth.go (1)

20-20: LGTM! Clean migration to sdk-go base controller.

The import path update from library-go factory to sdk-go basecontroller/factory aligns with the PR objective to leverage the contextual logger in the base controller. The field type on line 40 and controller usage remain compatible with the new factory package.

pkg/work/spoke/controllers/manifestcontroller/appliedmanifestwork_reconciler.go (2)

19-19: LGTM! Import migration to sdk-go base controller.

The import change from library-go factory to sdk-go basecontroller factory aligns with the PR objective to leverage the base controller framework. Based on learnings, the sdk-go factory provides typed queue interfaces which improve type safety.


32-32: LGTM! Appropriate use of blank identifier.

Using the blank identifier for the unused SyncContext parameter is correct and idiomatic. The reconciler doesn't need the SyncContext since it has its own rateLimiter field (line 27) and properly uses the contextual logger via klog.FromContext(ctx) (line 36).

pkg/work/spoke/spokeagent.go (2)

26-26: LGTM! Import updated to use builder package.

The import correctly switches to the new builder-based config loader from sdk-go, with a clear alias that makes the usage readable.


237-238: LGTM! Config loader usage correctly updated.

The function call correctly uses the new builder package while maintaining the same parameters and error handling pattern. This is a clean refactoring with no behavioral changes.

pkg/work/spoke/controllers/finalizercontroller/appliedmanifestwork_finalize_controller.go (3)

19-19: LGTM: Migration to sdk-go factory.

The import change from library-go to sdk-go basecontroller factory aligns with the PR objectives and provides typed queue interfaces for better type safety.


59-59: LGTM: Updated controller binding for sdk-go.

The ToController binding correctly follows the sdk-go pattern without passing a recorder parameter.


62-65: LGTM: Explicit parameter and contextual logging setup.

The sync method signature change makes the appliedManifestWorkName explicit, and the logger initialization correctly establishes contextual logging that propagates downstream. This pattern ensures better observability and aligns with the sdk-go base controller approach.

pkg/work/spoke/controllers/finalizercontroller/unmanaged_appliedmanifestwork_controller.go (1)

21-21: LGTM! Clean migration to sdk-go base controller.

The migration from library-go/pkg/controller/factory to sdk-go/pkg/basecontroller/factory is correctly implemented:

  • Import path updated to use sdk-go (line 21)
  • WithInformersQueueKeyFuncWithInformersQueueKeysFunc with proper []string return type (lines 80-82)
  • ToController call updated to remove the recorder parameter (line 87)
  • sync method signature correctly extended with explicit appliedManifestWorkName string parameter (line 90)
  • Contextual logger properly initialized using the provided key parameter (lines 91-93)

The queue operations at line 147 (Queue().AddAfter) are compatible with the new typed queue interface TypedRateLimitingInterface[string].

Based on learnings.

Also applies to: 80-87, 90-93

pkg/work/spoke/auth/cache/executor_cache_controller.go (4)

20-20: LGTM: Migration to sdk-go base controller factory.

The import change aligns with the PR objective to leverage contextual logging in the base controller. Based on learnings, this factory provides a typed queue interface (TypedRateLimitingInterface[string]) compared to the previous library-go factory.

Based on learnings


111-111: LGTM: API signature updates for sdk-go factory.

The updated signatures for NewSyncContext and ToController correctly reflect the new sdk-go base controller API, which no longer requires the recorder parameter at these construction points.

Also applies to: 140-140


257-260: LGTM: Contextual logging correctly implemented.

The sync method signature update correctly adopts the new pattern where executorKey is passed directly as a parameter. The contextual logging implementation follows best practices: extracting the logger from context, enriching it with the executorKey, and propagating it through the call chain.


263-263: LGTM: Structured logging adoption.

The migration to structured logging using logger.Info() with key-value pairs is a best practice improvement over formatted strings. The logger correctly inherits the executorKey context set in the sync method through context propagation.

Also applies to: 265-265, 281-281, 293-293

pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler_test.go (2)

378-379: LGTM!

The test correctly uses NewFakeSDKSyncContext and passes work.Name as the key parameter to the sync method, aligning with the new SDK-based controller pattern.


900-900: LGTM!

The queue creation correctly uses the typed NewTypedRateLimitingQueue[string] with the appropriate typed rate limiter, consistent with the SDK migration.

pkg/work/hub/controllers/manifestworkgarbagecollection/controller_test.go (1)

92-93: LGTM!

The test correctly uses NewFakeSDKSyncContext and passes the key "default/test" to the sync method, consistent with the SDK-based controller pattern.

pkg/work/hub/controllers/manifestworkgarbagecollection/controller.go (3)

20-20: LGTM!

The import correctly switches from github.com/openshift/library-go/pkg/controller/factory to open-cluster-management.io/sdk-go/pkg/basecontroller/factory, aligning with the SDK migration. Based on learnings, the sdk-go factory returns a typed queue interface.


48-48: LGTM!

The ToController call is correctly updated to match the sdk-go factory pattern by removing the recorder parameter.


52-60: LGTM!

The sync method signature correctly accepts the key parameter directly instead of retrieving it via controllerContext.QueueKey(). The key is properly split into namespace and name components and logged appropriately.

pkg/common/testing/fake_sync_context.go (1)

29-33: The review comment is incorrect.

FakeSDKSyncContext correctly implements the SyncContext interface from open-cluster-management.io/sdk-go, which only requires the Queue() method. The spokeName and recorder fields are used during initialization but do not need to be exposed as methods, since the sdk-go interface doesn't require them.

The existing FakeSyncContext exposes QueueKey() and Recorder() methods because it implements the separate openshift/library-go factory interface, which has different requirements. These are two distinct interfaces for different factory implementations—not variations of the same interface.

Likely an incorrect or invalid review comment.

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controllers_test.go (1)

248-249: LGTM! Test correctly updated for new SDK sync signature.

The test properly migrates to NewFakeSDKSyncContext and passes the explicit key parameter to match the updated sync method signature. The key format (namespace/name) aligns with the controller's expectation.

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_controller.go (4)

30-30: LGTM! Migration to sdk-go basecontroller factory.

The import correctly switches to the sdk-go basecontroller factory, which provides typed queue interfaces and contextual logging support.

Based on learnings


104-114: LGTM! Queue key function correctly migrated to multi-key contract.

The function now returns []string to support the sdk-go basecontroller's multi-key per event capability. Empty results ([]string{}) and single-key results ([]string{"namespace/name"}) are correctly represented.


120-120: LGTM! ToController correctly updated.

The recorder parameter is removed as the sdk-go basecontroller now handles event recording internally with contextual logging support, aligning with the PR's objective.


157-160: LGTM! Sync signature correctly updated with contextual logging.

The sync method now receives an explicit key parameter and initializes a contextual logger with structured fields. This aligns with the sdk-go basecontroller pattern and enables better observability throughout the reconciliation flow.

Based on learnings

pkg/common/queue/queuekey.go (1)

10-15: Inconsistent return types across filter functions in the same file.

The change removes the factory.EventFilterFunc type from FileterByLabel's return signature, making it return func(obj interface{}) bool directly. This creates an inconsistency:

  • FileterByLabel now returns: func(obj interface{}) bool
  • FileterByLabelKeyValue (line 17) still returns: factory.EventFilterFunc
  • FilterByNames (line 24) still returns: factory.EventFilterFunc

While these types are structurally identical and the code likely compiles, mixing named and unnamed versions of the same function type across a single module is poor API design and suggests incomplete migration. Either all three functions should use the same type, or the change should be reverted.

Additionally, the pre-existing typo in the function name ("Fileter" vs "Filter") remains.

pkg/work/helper/helpers.go (2)

32-32: LGTM! Import migrated to sdk-go base controller.

The import change from library-go factory to sdk-go basecontroller factory aligns with the PR objective to leverage the base controller with contextual logging.

Based on learnings


301-309: Function signature correctly migrated to support multiple queue keys—all call sites verified.

The migration from ObjectQueueKeyFunc (returning string) to ObjectQueueKeysFunc (returning []string) is correctly implemented. The single usage at pkg/work/spoke/controllers/finalizercontroller/manifestwork_finalize_controller.go:62 properly invokes WithFilteredEventsInformersQueueKeysFunc(), which expects ObjectQueueKeysFunc. The logic is preserved: no prefix match returns an empty slice, and a match returns a single-element slice. The sdk-go factory import confirms compatibility with typed queue requirements.

pkg/common/recorder/logging_recorder.go (1)

33-37: LGTM!

The method correctly creates a new instance to avoid mutation, and appropriately preserves the context from the original recorder.

Comment on lines +17 to +20
func (r *ContextualLoggingEventRecorder) WithContext(ctx context.Context) events.Recorder {
r.ctx = ctx
return r
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix race condition: WithContext mutates shared state.

The method mutates r.ctx directly and returns the same receiver. If the same recorder instance is shared across goroutines (common in controller setups), concurrent calls to WithContext will race on the ctx field, leading to nondeterministic context propagation.

Apply this diff to return a new instance:

 func (r *ContextualLoggingEventRecorder) WithContext(ctx context.Context) events.Recorder {
-	r.ctx = ctx
-	return r
+	newRecorder := *r
+	newRecorder.ctx = ctx
+	return &newRecorder
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (r *ContextualLoggingEventRecorder) WithContext(ctx context.Context) events.Recorder {
r.ctx = ctx
return r
}
func (r *ContextualLoggingEventRecorder) WithContext(ctx context.Context) events.Recorder {
newRecorder := *r
newRecorder.ctx = ctx
return &newRecorder
}
🤖 Prompt for AI Agents
In pkg/common/recorder/logging_recorder.go around lines 17 to 20, WithContext
currently mutates the receiver's ctx field which introduces a race when the
recorder is shared across goroutines; change it to return a new
ContextualLoggingEventRecorder instance (a shallow copy of the receiver) with
ctx set to the provided context so the original receiver is not mutated and
callers receive a separate recorder with the new context.

Comment on lines +22 to +27
// NewContextualLoggingEventRecorder provides event recorder that will log all recorded events via klog.
func NewContextualLoggingEventRecorder(component string) events.Recorder {
return &ContextualLoggingEventRecorder{
component: component,
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document nil‑context fallback or initialize ctx.

The constructor leaves ctx uninitialized (nil). When Event or Warning is called before WithContext, klog.FromContext(nil) falls back to the global logger, losing contextual information. Consider either initializing ctx to context.Background() or documenting that callers must invoke WithContext before logging.

Optional fix to initialize context:

 func NewContextualLoggingEventRecorder(component string) events.Recorder {
 	return &ContextualLoggingEventRecorder{
 		component: component,
+		ctx:       context.Background(),
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// NewContextualLoggingEventRecorder provides event recorder that will log all recorded events via klog.
func NewContextualLoggingEventRecorder(component string) events.Recorder {
return &ContextualLoggingEventRecorder{
component: component,
}
}
// NewContextualLoggingEventRecorder provides event recorder that will log all recorded events via klog.
func NewContextualLoggingEventRecorder(component string) events.Recorder {
return &ContextualLoggingEventRecorder{
component: component,
ctx: context.Background(),
}
}
🤖 Prompt for AI Agents
In pkg/common/recorder/logging_recorder.go around lines 22 to 27, the
constructor leaves the recorder's ctx nil which causes klog.FromContext(nil) to
fall back to the global logger; either initialize ctx to context.Background() in
NewContextualLoggingEventRecorder so the recorder always has a non‑nil context,
or update the constructor's doc comment to explicitly require callers to call
WithContext before Event/Warning; if choosing initialization, ensure the context
package is imported and set the struct's ctx field to context.Background() when
constructing the recorder.

Comment on lines +45 to +61
func (r *ContextualLoggingEventRecorder) Event(reason, message string) {
logger := klog.FromContext(r.ctx)
logger.Info(fmt.Sprintf("INFO: %s", message), "reason", reason)
}

func (r *ContextualLoggingEventRecorder) Eventf(reason, messageFmt string, args ...interface{}) {
r.Event(reason, fmt.Sprintf(messageFmt, args...))
}

func (r *ContextualLoggingEventRecorder) Warning(reason, message string) {
logger := klog.FromContext(r.ctx)
logger.Info(fmt.Sprintf("WARNING: %s", message), "reason", reason)
}

func (r *ContextualLoggingEventRecorder) Warningf(reason, messageFmt string, args ...interface{}) {
r.Warning(reason, fmt.Sprintf(messageFmt, args...))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Include component name in log output.

The component field is stored and managed via ForComponent and ComponentName, but never emitted in the actual log messages. Operators cannot distinguish which component produced a log entry, reducing the value of component-scoped recorders.

Apply this diff to include the component:

 func (r *ContextualLoggingEventRecorder) Event(reason, message string) {
 	logger := klog.FromContext(r.ctx)
-	logger.Info(fmt.Sprintf("INFO: %s", message), "reason", reason)
+	logger.Info(fmt.Sprintf("INFO: %s", message), "component", r.component, "reason", reason)
 }
 
 func (r *ContextualLoggingEventRecorder) Warning(reason, message string) {
 	logger := klog.FromContext(r.ctx)
-	logger.Info(fmt.Sprintf("WARNING: %s", message), "reason", reason)
+	logger.Info(fmt.Sprintf("WARNING: %s", message), "component", r.component, "reason", reason)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func (r *ContextualLoggingEventRecorder) Event(reason, message string) {
logger := klog.FromContext(r.ctx)
logger.Info(fmt.Sprintf("INFO: %s", message), "reason", reason)
}
func (r *ContextualLoggingEventRecorder) Eventf(reason, messageFmt string, args ...interface{}) {
r.Event(reason, fmt.Sprintf(messageFmt, args...))
}
func (r *ContextualLoggingEventRecorder) Warning(reason, message string) {
logger := klog.FromContext(r.ctx)
logger.Info(fmt.Sprintf("WARNING: %s", message), "reason", reason)
}
func (r *ContextualLoggingEventRecorder) Warningf(reason, messageFmt string, args ...interface{}) {
r.Warning(reason, fmt.Sprintf(messageFmt, args...))
}
func (r *ContextualLoggingEventRecorder) Event(reason, message string) {
logger := klog.FromContext(r.ctx)
logger.Info(fmt.Sprintf("INFO: %s", message), "component", r.component, "reason", reason)
}
func (r *ContextualLoggingEventRecorder) Eventf(reason, messageFmt string, args ...interface{}) {
r.Event(reason, fmt.Sprintf(messageFmt, args...))
}
func (r *ContextualLoggingEventRecorder) Warning(reason, message string) {
logger := klog.FromContext(r.ctx)
logger.Info(fmt.Sprintf("WARNING: %s", message), "component", r.component, "reason", reason)
}
func (r *ContextualLoggingEventRecorder) Warningf(reason, messageFmt string, args ...interface{}) {
r.Warning(reason, fmt.Sprintf(messageFmt, args...))
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant