-
Notifications
You must be signed in to change notification settings - Fork 33
Add Go SDK for GPUs #607
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add Go SDK for GPUs #607
Conversation
📝 WalkthroughWalkthroughThis pull request introduces a complete Kubernetes-native Go client library for the NVIDIA Device API with gRPC transport over Unix domain sockets. It adds GPU CRD type definitions, protobuf schema updates, a versioned clientset with informers and listers, gRPC infrastructure utilities, multiple example applications, and a custom Kubernetes-style code generation system supporting both protocol buffers and Go client generation. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Application
participant Clientset as versioned.Clientset
participant DeviceClient as DeviceV1alpha1Client
participant GPUInterface as gpus (GPUInterface)
participant gRPC as gRPC Conn
participant UDS as Device API<br/>(UDS)
Client->>Clientset: NewForConfig(config)
Clientset->>gRPC: nvgrpc.ClientConnFor(config)
gRPC->>UDS: Dial (Unix domain socket)
UDS-->>gRPC: Connection established
gRPC-->>Clientset: *grpc.ClientConn
Clientset-->>Client: *Clientset
Client->>Clientset: DeviceV1alpha1()
Clientset-->>Client: DeviceV1alpha1Client
Client->>DeviceClient: GPUs()
DeviceClient->>GPUInterface: newGPUs(client)
GPUInterface-->>Client: GPUInterface
Client->>GPUInterface: List(ctx, opts)
GPUInterface->>gRPC: ListGpus(ctx, request)
gRPC->>UDS: List GPUs over UDS
UDS-->>gRPC: *pb.GpuList response
gRPC-->>GPUInterface: Response received
GPUInterface->>GPUInterface: FromProtoList(pb.GpuList)
GPUInterface-->>Client: *devicev1alpha1.GPUList
sequenceDiagram
participant Factory as SharedInformerFactory
participant Informer as GPUInformer
participant Lister as GPULister
participant Cache as Indexer Cache
participant Source as gRPC Source
Factory->>Factory: Start()
Factory->>Informer: Launch per-informer goroutine
Informer->>Informer: defaultInformer()
Informer->>Source: List/Watch via gRPC
Source->>Source: Initial List snapshot
Source-->>Informer: Items added to cache
Informer->>Cache: Store objects in indexer
Cache-->>Informer: Sync complete
Factory->>Factory: WaitForCacheSync()
Informer-->>Factory: HasSynced reports true
Lister->>Cache: List(selector)
Cache-->>Lister: Filtered objects
Lister-->>Factory: Cached objects returned
Source->>Informer: Watch event (MODIFIED)
Informer->>Cache: Update indexer
Cache->>Lister: Query reflects new state
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
🧹 Nitpick comments (35)
client-go/nvgrpc/client_conn_test.go (1)
34-34: Check connection Close() errors in cleanup.The
conn.Close()errors are currently ignored. While unlikely to fail in tests, checking these errors follows best practices for resource cleanup.🔎 Proposed fix
- conn.Close() + if err := conn.Close(); err != nil { + t.Errorf("failed to close connection: %v", err) + }Also applies to: 47-47
client-go/DEVELOPMENT.md (1)
10-11: Optional markdown formatting improvements.Static analysis identified minor markdown style issues:
- Lines 10-11: List items could use 2-space indentation instead of 4
- Line 77: "inside of" could be simplified to "inside"
These are purely stylistic and don't affect readability or functionality.
🔎 Optional markdown fixes
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.Also applies to: 77-77
client-go/examples/streaming-daemon/main.go (2)
15-15: Missing package-level godoc comment.As per coding guidelines, package-level godoc is required for all Go packages. Consider adding a doc comment describing the purpose of this example.
+// Package main demonstrates a streaming daemon that watches GPU resources +// using the NVIDIA Device API client SDK with custom gRPC interceptors. package main
37-39: Consider usinglog/slogfor structured logging.The coding guidelines specify using
log/slogfor structured logging in Go code. Whilestdrprovides structured logging via the logr interface, consider aligning with the project's logging standard for consistency.api/proto/device/v1alpha1/gpu.proto (1)
27-51: Inconsistent indentation in comments.Lines 35-37 and 47-49 use tab indentation while other comment lines use spaces. This creates visual inconsistency in the proto file.
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/examples/fake-server/main.go (2)
15-15: Missing package-level godoc comment.As per coding guidelines, package-level godoc is required for all Go packages.
+// Package main provides a fake NVIDIA Device API server for testing +// the client SDK examples without requiring physical GPU hardware. package main
138-148: Consider adding a defensive check for conditions slice.Direct access to
Conditions[0]assumes the slice is non-empty. While the current initialization guarantees this, a defensive check would prevent potential panics if the initialization logic changes.Suggested defensive check
+ if len(gpu.Status.Conditions) == 0 { + s.mu.Unlock() + continue + } + // Toggle the Ready condition isReady := gpu.Status.Conditions[0].Status == metav1.ConditionTrueclient-go/examples/fake-server/README.md (1)
15-18: Consider documenting theNVIDIA_DEVICE_API_TARGETenvironment variable.The implementation supports customizing the socket path via
NVIDIA_DEVICE_API_TARGET, but this isn't mentioned in the README. This would help users who need to use a different socket location.Suggested addition
## Behavior - **Endpoint**: Defaults to `unix:///tmp/nvidia-device-api.sock` + - Override with the `NVIDIA_DEVICE_API_TARGET` environment variable - **Inventory**: Simulates 8 NVIDIA GPUs (`gpu-0` through `gpu-7`)client-go/Makefile (1)
187-187: Declaretoolstarget as PHONY.The
toolstarget has no corresponding file output and should be declared PHONY to ensure it always runs when invoked. Based on static analysis hint.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)client-go/version/version_test.go (1)
9-19: Refactor to use testify assertions and improve test naming.Per coding guidelines:
- Use
testify/assertortestify/requirefor assertions instead of rawt.Errorf- Test name should follow the format:
TestFunctionName_Scenario_ExpectedBehavior🔎 Proposed refactor using testify
+import ( + "github.com/stretchr/testify/assert" +) + -func TestUserAgent(t *testing.T) { +func TestUserAgent_WithCustomVersion_ReturnsFormattedString(t *testing.T) { originalVersion := GitVersion defer func() { GitVersion = originalVersion }() GitVersion = "v1.2.3-test" expected := fmt.Sprintf("nvidia-device-api-client/v1.2.3-test (%s/%s)", runtime.GOOS, runtime.GOARCH) - if got := UserAgent(); got != expected { - t.Errorf("UserAgent() = %q, want %q", got, expected) - } + assert.Equal(t, expected, UserAgent()) }Based on coding guidelines: Use
testify/assertandtestify/requirefor assertions in Go tests, and name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior.client-go/examples/README.md (1)
17-23: Clarify the working directory for running the fake server.The instructions show
go run ./fake-server/main.gobut don't specify which directory to execute this from. Based on the directory structure (lines 34-38), it appears the command should be run from theexamples/directory, but this isn't explicit.🔎 Proposed clarification
### 1. Start the Fake Server -The server creates a Unix domain socket (UDS) at `/tmp/nvidia-device-api.sock` and simulates a node with 8 GPUs. It also generates random status change events to test `Watch` and Informer capabilities. +The server creates a Unix domain socket (UDS) at `/tmp/nvidia-device-api.sock` and simulates a node with 8 GPUs. It also generates random status change events to test `Watch` and Informer capabilities. Run from the `examples/` directory: ```bash # Run this in a separate terminal +cd examples go run ./fake-server/main.go</details> </blockquote></details> <details> <summary>client-go/nvgrpc/options_test.go (1)</summary><blockquote> `25-65`: **Refactor to use testify assertions per coding guidelines.** The test uses raw `t.Errorf` calls instead of `testify/assert` or `testify/require` as specified in the coding guidelines. Consider refactoring for consistency with project standards. <details> <summary>🔎 Proposed refactor</summary> ```diff import ( "context" "testing" "github.com/go-logr/logr" + "github.com/stretchr/testify/assert" "google.golang.org/grpc" ) func TestDialOptions(t *testing.T) { testLogger := logr.Discard() dummyUnary := func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { return invoker(ctx, method, req, reply, cc, opts...) } dummyStream := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { return streamer(ctx, desc, cc, method, opts...) } opts := []DialOption{ WithLogger(testLogger), WithUnaryInterceptor(dummyUnary), WithStreamInterceptor(dummyStream), WithUnaryInterceptor(dummyUnary), // Test multiple appends WithStreamInterceptor(dummyStream), } dOpts := &dialOptions{} for _, opt := range opts { opt(dOpts) } t.Run("Logger is correctly assigned", func(t *testing.T) { - if dOpts.logger != testLogger { - t.Errorf("expected logger to be set, got %v", dOpts.logger) - } + assert.Equal(t, testLogger, dOpts.logger, "logger should be correctly assigned") }) t.Run("Unary interceptors are correctly appended", func(t *testing.T) { - if len(dOpts.unaryInterceptors) != 2 { - t.Errorf("expected 2 unary interceptors, got %d", len(dOpts.unaryInterceptors)) - } + assert.Len(t, dOpts.unaryInterceptors, 2, "should have 2 unary interceptors") }) t.Run("Stream interceptors are correctly appended", func(t *testing.T) { - if len(dOpts.streamInterceptors) != 2 { - t.Errorf("expected 2 stream interceptors, got %d", len(dOpts.streamInterceptors)) - } + assert.Len(t, dOpts.streamInterceptors, 2, "should have 2 stream interceptors") }) }Based on coding guidelines: Use
testify/assertandtestify/requirefor assertions in Go tests.client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
37-40: Simplify the nil return in generated overlay.The explicit
var ret *grpc.ClientConnfollowed byreturn retis unnecessarily verbose. Since this is part of the gRPC overlay (as indicated in line 15), consider simplifying toreturn nildirectly, which is clearer and more idiomatic.🔎 Proposed simplification
func (c *FakeDeviceV1alpha1) ClientConn() grpc.ClientConnInterface { - var ret *grpc.ClientConn - return ret + return nil }client-go/nvgrpc/config_test.go (1)
54-56: Consider using testify/assert for cleaner assertions.The tests use standard library error reporting (
t.Errorf,t.Error) instead of testify assertions. Per coding guidelines,testify/assertandtestify/requireare preferred for more readable test assertions and better failure messages.Example refactor using testify
+import ( + "github.com/stretchr/testify/assert" +) func TestConfig_Default_TargetPrecedence(t *testing.T) { // ... test setup ... for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Setenv(NvidiaDeviceAPITargetEnvVar, tt.envTarget) cfg := &Config{Target: tt.argTarget} cfg.Default() - if cfg.Target != tt.wantTarget { - t.Errorf("Target = %q, want %q", cfg.Target, tt.wantTarget) - } + assert.Equal(t, tt.wantTarget, cfg.Target) }) } }As per coding guidelines, using testify improves test readability and provides better assertion failure output.
Also applies to: 66-68, 76-78, 114-117
client-go/examples/basic-client/main.go (2)
39-45: Consider adding cleanup for the gRPC connection.The example creates a clientset over a gRPC connection but does not close it. For a complete example, consider adding deferred cleanup if the clientset or underlying connection supports it.
🔎 Possible approach if a Close method exists
clientset, err := versioned.NewForConfig(config) if err != nil { logger.Error(err, "unable to create clientset") os.Exit(1) } // If clientset has a Close method: // defer clientset.Close()
47-64: Consider using context with timeout for production use.The example uses
context.Background()for API calls, which is fine for a demo but lacks timeout protection. For production code, consider usingcontext.WithTimeoutto prevent hanging on slow or unresponsive connections.client-go/nvgrpc/interceptors.go (1)
15-15: Missing package-level godoc.As per coding guidelines, package-level godoc is required for all Go packages. Consider adding a package comment describing the purpose of the
nvgrpcpackage.Suggested package documentation
package nvgrpc + +// Package nvgrpc provides gRPC client utilities including interceptors, +// configuration, and connection management for the NVIDIA Device API.Note: If this documentation already exists in a
doc.gofile in the same package, this comment can be disregarded.client-go/hack/overlays/client/versioned/integration_test.go (2)
279-287: Consider using gRPC status codes for more realistic mock behavior.The mock returns a plain error for "not found" cases. For more realistic behavior matching gRPC semantics, consider returning a proper gRPC status error.
Suggested improvement
+import "google.golang.org/grpc/status" +import "google.golang.org/grpc/codes" func (m *mockGpuServer) GetGpu(ctx context.Context, req *pb.GetGpuRequest) (*pb.GetGpuResponse, error) { m.mu.RLock() defer m.mu.RUnlock() gpu, ok := m.gpus[req.Name] if !ok { - return nil, fmt.Errorf("%s not found", req.Name) + return nil, status.Errorf(codes.NotFound, "%s not found", req.Name) } return &pb.GetGpuResponse{Gpu: gpu}, nil }
50-55: Consider migrating from deprecatedgrpc.DialContexttogrpc.NewClientwith bufconn support.gRPC v1.63.0 introduced a new NewClient method to create a new ClientConn, and DialContext is marked as deprecated. For bufconn-based testing, the migration requires using the "passthrough" resolver scheme. Use one of these approaches:
- Specify the "passthrough" resolver in the target string, e.g. "passthrough:target"
- Or call resolver.SetDefaultScheme("passthrough") during initialization time (in an init() function), noting it is not thread-safe
client-go/examples/controller-shim/main.go (1)
15-15: Missing package-level godoc comment.Per coding guidelines, all Go packages require package-level documentation explaining the purpose of this example.
Suggested fix
+// Package main provides an example controller-shim that demonstrates +// wiring a gRPC-backed clientset into a controller-runtime manager, +// enabling GPU resource reconciliation without a real Kubernetes API server. package mainclient-go/nvgrpc/options.go (1)
15-15: Missing package-level godoc comment.Per coding guidelines, all Go packages require documentation.
Suggested fix
+// Package nvgrpc provides gRPC client configuration and connection utilities +// for the NVIDIA Device API, including dial options, interceptors, and logging. package nvgrpcclient-go/client/versioned/integration_test.go (2)
226-230: Goroutine error not reliably captured in test.The
t.Errorfinside the goroutine may execute after the test completes, causing the error to be missed or to panic. Consider using a channel orerrgroupto properly capture and check for errors.Suggested approach
+ cacheErrCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + cacheErrCh <- err } + close(cacheErrCh) }() + // Check for immediate startup errors + select { + case err := <-cacheErrCh: + if err != nil { + t.Fatalf("Cache failed to start: %v", err) + } + case <-time.After(100 * time.Millisecond): + // Cache started successfully + }
295-302: Mock server should return gRPC status errors.Returning a plain
fmt.Errorfdoesn't translate to proper gRPC status codes. The client may not correctly interpret this as a NotFound error. Usestatus.Errorfor proper gRPC semantics.Suggested fix
+import "google.golang.org/grpc/codes" +import "google.golang.org/grpc/status" func (m *mockGpuServer) GetGpu(ctx context.Context, req *pb.GetGpuRequest) (*pb.GetGpuResponse, error) { m.mu.RLock() defer m.mu.RUnlock() gpu, ok := m.gpus[req.Name] if !ok { - return nil, fmt.Errorf("%s not found", req.Name) + return nil, status.Errorf(codes.NotFound, "%s not found", req.Name) } return &pb.GetGpuResponse{Gpu: gpu}, nil }client-go/nvgrpc/watcher_test.go (3)
15-15: Missing package-level godoc.As per coding guidelines, package-level godoc is required for all Go packages. Consider adding a brief description of the test package purpose.
+// Package nvgrpc provides tests for the nvgrpc watcher implementation. package nvgrpc
153-160: Consider removingtime.Sleepto reduce test flakiness.Using
time.Sleep(10 * time.Millisecond)to "allow the receive loop to start" is fragile and can cause intermittent failures under load. Consider using synchronization primitives or restructuring to avoid timing dependencies.🔎 Suggested approach
One approach is to have
NewWatchersignal when the receive goroutine has started, or use a channel-based synchronization in the test helper:func TestWatcher_Stop(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) source := NewFakeSource() w := NewWatcher(source, cancel, logr.Discard()) - // Allow the receive loop to start - time.Sleep(10 * time.Millisecond) + // Send a dummy event to ensure receive loop is running + source.events <- testEvent{"ADDED", &FakeObject{Name: "sync"}} + <-w.ResultChan() // Drain the sync event w.Stop()
49-57: Consider using testify for assertions per coding guidelines.The coding guidelines specify using
testify/assertandtestify/requirefor assertions. While the current assertions are functionally correct, using testify would improve consistency and provide better failure messages.🔎 Example refactor
+import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + // In TestWatcher_NormalEvents: - wantTypes := []watch.EventType{watch.Added, watch.Modified, watch.Deleted} - if len(got) != len(wantTypes) { - t.Fatalf("got %d events, want %d", len(got), len(wantTypes)) - } - for i, ev := range got { - if ev.Type != wantTypes[i] { - t.Errorf("event %d: got type %v, want %v", i, ev.Type, wantTypes[i]) - } - } + wantTypes := []watch.EventType{watch.Added, watch.Modified, watch.Deleted} + require.Len(t, got, len(wantTypes)) + for i, ev := range got { + assert.Equal(t, wantTypes[i], ev.Type, "event %d", i) + }client-go/hack/overlays/client/versioned/clientset.go (1)
1-1: Missing package-level godoc.As per coding guidelines, package-level godoc is required. Consider adding documentation describing the purpose of this versioned clientset package.
+// Package versioned provides a typed client for the NVIDIA Device API, +// exposing Kubernetes-style accessors over a gRPC connection. package versionedclient-go/nvgrpc/config.go (1)
15-15: Missing package-level godoc.As per coding guidelines, package-level godoc is required for all Go packages.
+// Package nvgrpc provides configuration and utilities for connecting to the +// NVIDIA Device API via gRPC, including connection setup, interceptors, and +// watch stream handling. package nvgrpcclient-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
15-17: Package-level godoc is missing.As per coding guidelines, package-level godoc is required for all Go packages. Consider adding a package comment describing the purpose of this v1alpha1 client package.
+// Package v1alpha1 contains the typed client for the device.nvidia.com/v1alpha1 API group. package v1alpha1client-go/client/versioned/clientset.go (1)
48-60: Redundant shallow copy when callingNewForConfigAndClient.Line 53 creates a shallow copy, but
NewForConfigAndClient(line 72) creates another shallow copy. Since you're already passing the address ofconfigShallowCopy, the second copy is unnecessary overhead.🔎 Suggested simplification in NewForConfigAndClient
Either remove the shallow copy from
NewForConfigAndClientsince callers are expected to pass already-copied configs, or document thatNewForConfigAndClienttakes ownership and copies internally. For consistency with the parentClientset.NewForConfig, you might keep it for safety when called directly.client-go/client/versioned/typed/device/v1alpha1/device_client.go (2)
53-60:NewForConfigAndClientreturns an error but never fails.The function signature returns
error, but the implementation always returnsnil. This is consistent with the Kubernetes pattern for future extensibility, but consider adding a comment explaining this is for API compatibility.
73-79:New()useslogr.Discard(), which silently drops all logs.When using
New(conn)directly, all logging is discarded. Consider documenting this behavior or providing aNewWithLoggervariant for users who want observability without full config setup.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
1-7: Missing license header and generated-code disclaimer.Other files in this PR include the Apache 2.0 license header and "DO NOT EDIT" comment. This overlay file is missing both, which is inconsistent with the rest of the codebase.
🔎 Add license header
+// Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package v1alpha1client-go/nvgrpc/watcher.go (1)
15-15: Package-level godoc is missing.As per coding guidelines, package-level godoc is required. Consider adding documentation describing the nvgrpc package's purpose.
client-go/informers/externalversions/factory.go (1)
169-173: Minor typo in variable name.The variable
informTypeshould beinformerTypefor consistency with the rest of the codebase. However, since this is generated code (line 15), this should be fixed in the generator template rather than here.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**api/go.sumis excluded by!**/*.sumclient-go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (71)
.gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/device/v1alpha1/zz_generated.conversion.go(1 hunks)api/device/v1alpha1/zz_generated.deepcopy.go(1 hunks)api/go.mod(1 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/client/versioned/clientset.go(1 hunks)client-go/client/versioned/fake/clientset_generated.go(1 hunks)client-go/client/versioned/fake/doc.go(1 hunks)client-go/client/versioned/fake/register.go(1 hunks)client-go/client/versioned/integration_test.go(1 hunks)client-go/client/versioned/scheme/doc.go(1 hunks)client-go/client/versioned/scheme/register.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/generated_expansion.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/informers/externalversions/device/interface.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/gpu.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/interface.go(1 hunks)client-go/informers/externalversions/factory.go(1 hunks)client-go/informers/externalversions/generic.go(1 hunks)client-go/informers/externalversions/internalinterfaces/factory_interfaces.go(1 hunks)client-go/listers/device/v1alpha1/expansion_generated.go(1 hunks)client-go/listers/device/v1alpha1/gpu.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/client/versioned/typed/device/v1alpha1/generated_expansion.goclient-go/listers/device/v1alpha1/expansion_generated.goapi/device/v1alpha1/doc.goclient-go/nvgrpc/interceptors_test.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/version/version_test.goclient-go/client/versioned/fake/doc.goclient-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/informers/externalversions/internalinterfaces/factory_interfaces.goapi/device/v1alpha1/register.goclient-go/nvgrpc/client_conn_test.goclient-go/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/interceptors.goclient-go/nvgrpc/watcher_test.goclient-go/nvgrpc/client_conn.goclient-go/client/versioned/typed/device/v1alpha1/fake/doc.goclient-go/nvgrpc/options.goclient-go/client/versioned/scheme/register.goapi/device/v1alpha1/gpu_types.goclient-go/client/versioned/integration_test.goclient-go/listers/device/v1alpha1/gpu.goclient-go/version/version.goapi/device/v1alpha1/gpu_conversion.goclient-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.goclient-go/informers/externalversions/device/interface.goclient-go/client/versioned/typed/device/v1alpha1/gpu.goclient-go/nvgrpc/config.goclient-go/informers/externalversions/device/v1alpha1/interface.goclient-go/examples/basic-client/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goapi/device/v1alpha1/converter.goclient-go/informers/externalversions/generic.goclient-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goapi/device/v1alpha1/zz_generated.deepcopy.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/client/versioned/typed/device/v1alpha1/doc.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/watcher.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/informers/externalversions/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/client/versioned/clientset.goclient-go/examples/streaming-daemon/main.goclient-go/client/versioned/scheme/doc.goclient-go/examples/fake-server/main.goclient-go/client/versioned/fake/register.goclient-go/nvgrpc/config_test.goapi/device/v1alpha1/zz_generated.conversion.goclient-go/informers/externalversions/factory.goclient-go/client/versioned/fake/clientset_generated.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/interceptors_test.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/version/version_test.goclient-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/watcher_test.goclient-go/client/versioned/integration_test.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/config_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
api/go.modclient-go/go.mod
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/hack/boilerplate_overlay.go.txtclient-go/examples/basic-client/README.mdclient-go/examples/README.mdclient-go/client/versioned/fake/doc.go.versions.yamlclient-go/hack/apply-overlays.shclient-go/nvgrpc/client_conn.goclient-go/client/versioned/scheme/register.goclient-go/README.mdclient-go/client/versioned/typed/device/v1alpha1/gpu.goclient-go/examples/basic-client/main.goapi/go.modclient-go/hack/overlays/client/versioned/clientset.goclient-go/client/versioned/typed/device/v1alpha1/doc.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/watcher.go.gitignoreclient-go/client/versioned/scheme/doc.goclient-go/DEVELOPMENT.mdclient-go/go.modclient-go/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
client-go/hack/boilerplate.go.txtapi/hack/boilerplate.go.txt
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/examples/README.mdclient-go/version/version_test.goclient-go/client/versioned/fake/doc.go.versions.yamlclient-go/client/versioned/typed/device/v1alpha1/fake/doc.goclient-go/client/versioned/integration_test.goclient-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/integration_test.go.gitignoreclient-go/go.modclient-go/client/versioned/fake/clientset_generated.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/client/versioned/fake/doc.goclient-go/client/versioned/typed/device/v1alpha1/doc.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
.versions.yamlapi/go.modclient-go/go.modapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
api/hack/boilerplate.go.txt
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Extract informer event handler setup into helper methods
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.goclient-go/informers/externalversions/factory.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.goclient-go/informers/externalversions/device/v1alpha1/gpu.goclient-go/informers/externalversions/factory.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.goclient-go/nvgrpc/watcher.goclient-go/informers/externalversions/device/v1alpha1/gpu.goclient-go/go.modclient-go/informers/externalversions/factory.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
api/go.modclient-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.gitignore
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/Makefile
🧬 Code graph analysis (29)
client-go/nvgrpc/interceptors_test.go (1)
client-go/nvgrpc/interceptors.go (2)
NewLatencyUnaryInterceptor(28-59)NewLatencyStreamInterceptor(62-92)
api/device/v1alpha1/gpu_conversion_test.go (2)
api/device/v1alpha1/gpu_conversion.go (4)
FromProto(25-32)ToProto(35-40)FromProtoList(43-48)ToProtoList(51-56)api/gen/go/device/v1alpha1/gpu.pb.go (21)
Gpu(159-169)Gpu(182-182)Gpu(197-199)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)GpuStatus(325-333)GpuStatus(346-346)GpuStatus(361-363)Condition(380-398)Condition(411-411)Condition(426-428)GpuList(223-230)GpuList(243-243)GpuList(258-260)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)
client-go/version/version_test.go (1)
client-go/version/version.go (2)
GitVersion(25-25)UserAgent(28-35)
client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(38-43)
client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (2)
api/gen/go/device/v1alpha1/gpu_grpc.pb.go (1)
GpuService_WatchGpusClient(100-100)api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
client-go/informers/externalversions/internalinterfaces/factory_interfaces.go (4)
client-go/client/versioned/clientset.go (1)
Interface(28-30)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/informers/externalversions/device/interface.go (1)
Interface(25-28)client-go/informers/externalversions/device/v1alpha1/interface.go (1)
Interface(24-27)
api/device/v1alpha1/register.go (1)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/nvgrpc/client_conn_test.go (4)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(27-72)client-go/version/version.go (1)
UserAgent(28-35)client-go/nvgrpc/options.go (1)
WithLogger(32-36)
client-go/client/versioned/typed/device/v1alpha1/device_client.go (2)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(27-72)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(47-62)
client-go/nvgrpc/client_conn.go (4)
client-go/nvgrpc/config.go (3)
Config(41-49)DefaultKeepAliveTime(34-34)DefaultKeepAliveTimeout(37-37)client-go/nvgrpc/options.go (1)
DialOption(23-23)client-go/version/version.go (1)
UserAgent(28-35)client-go/nvgrpc/interceptors.go (2)
NewLatencyUnaryInterceptor(28-59)NewLatencyStreamInterceptor(62-92)
api/device/v1alpha1/gpu_types.go (1)
api/gen/go/device/v1alpha1/gpu.pb.go (9)
Condition(380-398)Condition(411-411)Condition(426-428)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)
api/device/v1alpha1/gpu_conversion.go (4)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/zz_generated.conversion.go (1)
ConverterImpl(11-11)api/gen/go/device/v1alpha1/gpu.pb.go (6)
Gpu(159-169)Gpu(182-182)Gpu(197-199)GpuList(223-230)GpuList(243-243)GpuList(258-260)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go (6)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
FakeDeviceV1alpha1(25-27)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
FakeDeviceV1alpha1(9-11)client-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(38-43)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/informers/externalversions/device/interface.go (5)
client-go/informers/externalversions/device/v1alpha1/interface.go (2)
Interface(24-27)New(36-38)client-go/informers/externalversions/factory.go (1)
SharedInformerFactory(224-256)client-go/informers/externalversions/internalinterfaces/factory_interfaces.go (2)
SharedInformerFactory(32-35)TweakListOptionsFunc(38-38)client-go/client/versioned/typed/device/v1alpha1/device_client.go (1)
New(74-79)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
New(58-63)
client-go/informers/externalversions/device/v1alpha1/interface.go (1)
client-go/informers/externalversions/device/v1alpha1/gpu.go (1)
GPUInformer(35-38)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (2)
api/gen/go/device/v1alpha1/gpu_grpc.pb.go (1)
GpuService_WatchGpusClient(100-100)api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
api/device/v1alpha1/converter.go (3)
api/gen/go/device/v1alpha1/gpu.pb.go (21)
Gpu(159-169)Gpu(182-182)Gpu(197-199)GpuList(223-230)GpuList(243-243)GpuList(258-260)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)GpuStatus(325-333)GpuStatus(346-346)GpuStatus(361-363)Condition(380-398)Condition(411-411)Condition(426-428)api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/informers/externalversions/generic.go (1)
api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
api/device/v1alpha1/zz_generated.deepcopy.go (1)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/client/versioned/typed/device/v1alpha1/device_client.go (5)
DeviceV1alpha1Interface(25-28)DeviceV1alpha1Client(31-34)NewForConfig(43-51)NewForConfigAndClient(55-60)New(74-79)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(27-72)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
client-go/client/versioned/clientset.go (4)
NewForConfig(48-60)NewForConfigAndClient(64-81)NewForConfigOrDie(85-92)New(95-99)client-go/nvgrpc/config.go (1)
Config(41-49)
client-go/hack/overlays/client/versioned/integration_test.go (3)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/client/versioned/clientset.go (2)
NewForConfigAndClient(64-81)New(95-99)api/gen/go/device/v1alpha1/gpu.pb.go (18)
WatchGpusResponse(696-713)WatchGpusResponse(726-726)WatchGpusResponse(741-743)Gpu(159-169)Gpu(182-182)Gpu(197-199)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)GpuList(223-230)GpuList(243-243)GpuList(258-260)WatchGpusRequest(650-656)WatchGpusRequest(669-669)WatchGpusRequest(684-686)
client-go/informers/externalversions/device/v1alpha1/gpu.go (6)
client-go/listers/device/v1alpha1/gpu.go (1)
GPULister(28-36)client-go/informers/externalversions/internalinterfaces/factory_interfaces.go (2)
SharedInformerFactory(32-35)TweakListOptionsFunc(38-38)client-go/client/versioned/clientset.go (1)
Interface(28-30)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/informers/externalversions/device/v1alpha1/interface.go (1)
Interface(24-27)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (3)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)api/gen/go/device/v1alpha1/gpu_grpc.pb.go (1)
GpuServiceClient(46-53)api/gen/go/device/v1alpha1/gpu.pb.go (9)
GetGpuRequest(466-472)GetGpuRequest(485-485)GetGpuRequest(500-502)ListGpusRequest(558-564)ListGpusRequest(577-577)ListGpusRequest(592-594)WatchGpusRequest(650-656)WatchGpusRequest(669-669)WatchGpusRequest(684-686)
client-go/examples/fake-server/main.go (3)
api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/gen/go/device/v1alpha1/gpu.pb.go (9)
ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)Gpu(159-169)Gpu(182-182)Gpu(197-199)WatchGpusResponse(696-713)WatchGpusResponse(726-726)WatchGpusResponse(741-743)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/nvgrpc/config_test.go (2)
client-go/nvgrpc/config.go (3)
DefaultNvidiaDeviceAPISocket(31-31)NvidiaDeviceAPITargetEnvVar(28-28)Config(41-49)client-go/version/version.go (1)
UserAgent(28-35)
api/device/v1alpha1/zz_generated.conversion.go (3)
api/gen/go/device/v1alpha1/gpu.pb.go (21)
Gpu(159-169)Gpu(182-182)Gpu(197-199)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)Condition(380-398)Condition(411-411)Condition(426-428)GpuList(223-230)GpuList(243-243)GpuList(258-260)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)GpuStatus(325-333)GpuStatus(346-346)GpuStatus(361-363)api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/converter.go (4)
FromProtobufTypeMeta(107-112)FromProtobufTimestamp(123-128)FromProtobufListTypeMeta(115-120)ToProtobufTimestamp(131-133)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
f4e8d48 to
9b3add0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (7)
client-go/hack/overlays/client/versioned/integration_test.go (1)
210-214: Avoid callingt.Errorffrom a goroutine.This issue was already flagged in a previous review. Calling
t.Errorffrom a goroutine is unsafe and can cause race conditions. Consider using an error channel pattern as suggested previously.client-go/nvgrpc/watcher.go (1)
64-77: Race condition inStop()with double-close protection.This is a known issue already flagged in previous reviews. The
selecton lines 72-76 attempts to prevent double-close ofw.done, but there's a race window between checking<-w.doneand callingclose(w.done). Additionally,receive()callsdefer w.Stop()(line 90), which could race with an externalStop()call.client-go/informers/externalversions/factory.go (1)
200-224: Documentation references non-existent method.This is a known issue already flagged in previous reviews. The example documentation references
factory.WaitForStop()on line 208, but the actual method isShutdown(). Since this is generated code, the fix should be applied to the generator template.client-go/client/versioned/fake/clientset_generated.go (1)
52-53: Typo in variable name:watchActcionshould bewatchAction.This typo was already identified in a previous review.
client-go/examples/controller-shim/main.go (1)
58-62: The informer factory is never started.This issue was already flagged in a previous review. The comment on line 60 is incorrect—controller-runtime only starts informers created through its own cache machinery, not externally injected ones.
api/Makefile (2)
124-131: Undefined variableAPI_PKGS_COMMAwill cause build failure.Line 128 references
API_PKGS_COMMA, but onlyAPI_VERSIONS_COMMA(line 31) andAPI_PKGS(line 34) are defined. This will pass an empty string to--bounding-dirs.🔎 Proposed fix: Add the missing variable definition
Add near line 35 after
API_PKGS:# Helper for tools that need full package paths API_PKGS := $(foreach version,$(API_VERSIONS),$(MODULE_NAME)/$(version)) + +# Helper for tools that need comma-separated package paths +API_PKGS_COMMA := $(subst $(SPACE),$(COMMA),$(API_PKGS))
134-134: Minor typo: double period in help text.🔎 Proposed fix
-conversion-gen: $(GOVERTER) clean-conversion ## Generate conversion code.. +conversion-gen: $(GOVERTER) clean-conversion ## Generate conversion code.
🧹 Nitpick comments (12)
client-go/DEVELOPMENT.md (2)
77-77: Optional: Simplify phrasing.Static analysis suggests "inside" instead of "inside of" for more concise writing.
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.
10-11: Optional: Fix markdown list indentation.The nested list items use 4-space indentation, but markdownlint expects 2 spaces for consistency.
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)client-go/hack/overlays/client/versioned/integration_test.go (2)
50-56: Consider usinggrpc.NewClientinstead of deprecatedgrpc.DialContext.
grpc.DialContextis deprecated in gRPC v1.60+. For new code,grpc.NewClientis preferred. However, since this is test code and bufconn integration withNewClientcan be trickier, this is a low-priority change.
279-287: Consider returning a gRPC status error for "not found" case.Returning
status.Errorf(codes.NotFound, "%s not found", req.Name)instead offmt.Errorfwould better simulate real gRPC server behavior, which could be important if tests need to verify error handling based on gRPC status codes.Suggested fix
+import "google.golang.org/grpc/status" +import "google.golang.org/grpc/codes" func (m *mockGpuServer) GetGpu(ctx context.Context, req *pb.GetGpuRequest) (*pb.GetGpuResponse, error) { m.mu.RLock() defer m.mu.RUnlock() gpu, ok := m.gpus[req.Name] if !ok { - return nil, fmt.Errorf("%s not found", req.Name) + return nil, status.Errorf(codes.NotFound, "%s not found", req.Name) } return &pb.GetGpuResponse{Gpu: gpu}, nil }client-go/nvgrpc/config.go (1)
40-49: Consider documenting how to configure the logger.The
loggerfield is unexported, making it unclear how callers set a custom logger. If there's aWithLoggeroption (mentioned in related files likeoptions.go), consider adding a brief comment here or in the package documentation pointing to that mechanism.api/device/v1alpha1/gpu_types.go (1)
15-15: Missing package-level godoc comment.As per coding guidelines, package-level godoc is required for all Go packages. Consider adding a package comment describing the v1alpha1 API types.
Suggested fix
+// Package v1alpha1 contains API types for the device.nvidia.com/v1alpha1 API group. +// It defines GPU resources that represent physical GPU hardware on a node. package v1alpha1client-go/examples/controller-shim/main.go (1)
15-15: Missing package-level godoc comment.As per coding guidelines, package-level godoc is required. Consider adding a comment describing this example's purpose.
Suggested fix
+// Package main demonstrates integrating the NVIDIA Device API gRPC client +// with controller-runtime by injecting a gRPC-backed informer into the Manager's cache. package mainclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
1-7: Missing license header in overlay file.Unlike the main
device_client.go, this overlay file lacks the Apache 2.0 license header. Consider adding it for consistency across the codebase.🔎 Proposed fix
+// Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package v1alpha1client-go/Makefile (1)
187-187: Target "tools" should be declared PHONY.The
toolstarget has no corresponding file and should be declared as.PHONYto ensure it always runs when invoked.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)api/device/v1alpha1/zz_generated.conversion.go (3)
1-4: Missing package documentation.The coding guidelines require package-level godoc for all Go packages. Since this is generated code, consider updating the generator configuration to emit a package comment.
11-11: Missing type documentation.The exported
ConverterImpltype lacks a godoc comment. Since this is generated code, consider configuring the generator to emit documentation for exported types.
13-22: Conversion logic is correct.The nil-safety and field mappings are properly implemented. The zero-value return for nil input is appropriate. However, the exported method lacks a godoc comment—consider configuring the generator to emit documentation.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**api/go.sumis excluded by!**/*.sumclient-go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (73)
.gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/device/v1alpha1/zz_generated.conversion.go(1 hunks)api/device/v1alpha1/zz_generated.deepcopy.go(1 hunks)api/go.mod(1 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/client/versioned/clientset.go(1 hunks)client-go/client/versioned/fake/clientset_generated.go(1 hunks)client-go/client/versioned/fake/doc.go(1 hunks)client-go/client/versioned/fake/register.go(1 hunks)client-go/client/versioned/integration_test.go(1 hunks)client-go/client/versioned/scheme/doc.go(1 hunks)client-go/client/versioned/scheme/register.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/generated_expansion.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/informers/externalversions/device/interface.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/gpu.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/interface.go(1 hunks)client-go/informers/externalversions/factory.go(1 hunks)client-go/informers/externalversions/generic.go(1 hunks)client-go/informers/externalversions/internalinterfaces/factory_interfaces.go(1 hunks)client-go/listers/device/v1alpha1/expansion_generated.go(1 hunks)client-go/listers/device/v1alpha1/gpu.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)event-exporter/pkg/transformer/cloudevents.go(1 hunks)event-exporter/pkg/transformer/cloudevents_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- client-go/README.md
- api/hack/boilerplate.go.txt
- api/device/v1alpha1/doc.go
🚧 Files skipped from review as they are similar to previous changes (34)
- client-go/hack/boilerplate.go.txt
- client-go/nvgrpc/options_test.go
- api/device/v1alpha1/register.go
- client-go/examples/basic-client/README.md
- .gitignore
- client-go/version/version_test.go
- client-go/hack/apply-overlays.sh
- client-go/listers/device/v1alpha1/gpu.go
- client-go/examples/streaming-daemon/README.md
- client-go/nvgrpc/client_conn.go
- client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
- client-go/hack/overlays/client/versioned/clientset.go
- api/device/v1alpha1/gpu_conversion_test.go
- client-go/informers/externalversions/device/v1alpha1/gpu.go
- client-go/listers/device/v1alpha1/expansion_generated.go
- client-go/nvgrpc/options.go
- client-go/version/version.go
- client-go/examples/fake-server/main.go
- client-go/examples/fake-server/README.md
- client-go/informers/externalversions/device/interface.go
- client-go/nvgrpc/interceptors_test.go
- client-go/nvgrpc/client_conn_test.go
- client-go/informers/externalversions/device/v1alpha1/interface.go
- client-go/nvgrpc/interceptors.go
- client-go/client/versioned/typed/device/v1alpha1/gpu.go
- .versions.yaml
- client-go/nvgrpc/config_test.go
- api/device/v1alpha1/converter.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
- api/device/v1alpha1/gpu_conversion.go
- client-go/client/versioned/fake/register.go
- client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go
- client-go/examples/basic-client/main.go
- client-go/client/versioned/fake/doc.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goevent-exporter/pkg/transformer/cloudevents_test.goapi/device/v1alpha1/zz_generated.deepcopy.goclient-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/client/versioned/typed/device/v1alpha1/generated_expansion.goclient-go/client/versioned/integration_test.goclient-go/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/client/versioned/fake/clientset_generated.goclient-go/client/versioned/scheme/register.goclient-go/client/versioned/typed/device/v1alpha1/doc.goclient-go/informers/externalversions/factory.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/watcher_test.goclient-go/client/versioned/typed/device/v1alpha1/fake/doc.goapi/device/v1alpha1/gpu_types.goevent-exporter/pkg/transformer/cloudevents.goclient-go/examples/controller-shim/main.goclient-go/client/versioned/scheme/doc.goapi/device/v1alpha1/zz_generated.conversion.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/informers/externalversions/generic.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/config.goclient-go/client/versioned/clientset.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
event-exporter/pkg/transformer/cloudevents_test.goclient-go/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/integration_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
client-go/go.modapi/go.mod
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Extract informer event handler setup into helper methods
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/factory.goclient-go/informers/externalversions/generic.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/factory.goclient-go/nvgrpc/watcher.goclient-go/go.modclient-go/informers/externalversions/generic.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/client/versioned/fake/clientset_generated.goclient-go/examples/README.mdclient-go/nvgrpc/watcher_test.goclient-go/client/versioned/typed/device/v1alpha1/fake/doc.goclient-go/go.modclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/client/versioned/fake/clientset_generated.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/client/versioned/scheme/register.goclient-go/client/versioned/typed/device/v1alpha1/doc.goapi/Makefileclient-go/examples/README.mdclient-go/nvgrpc/watcher.goclient-go/go.modclient-go/client/versioned/scheme/doc.goapi/go.modclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/Makefileclient-go/hack/boilerplate_overlay.go.txtclient-go/DEVELOPMENT.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/client/versioned/typed/device/v1alpha1/doc.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
api/Makefileclient-go/go.modapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/informers/externalversions/factory.goclient-go/nvgrpc/watcher.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
client-go/go.modapi/go.mod
🧬 Code graph analysis (11)
client-go/examples/streaming-daemon/main.go (5)
client-go/client/versioned/clientset.go (2)
New(95-99)NewForConfigAndClient(64-81)client-go/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(74-79)NewForConfigAndClient(55-60)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(58-63)NewForConfigAndClient(39-44)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(27-72)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (2)
api/gen/go/device/v1alpha1/gpu_grpc.pb.go (1)
GpuService_WatchGpusClient(100-100)api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
api/device/v1alpha1/zz_generated.deepcopy.go (1)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)
client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(38-43)
client-go/client/versioned/integration_test.go (3)
client-go/client/versioned/clientset.go (2)
NewForConfigAndClient(64-81)New(95-99)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)api/gen/go/device/v1alpha1/gpu.pb.go (12)
WatchGpusResponse(696-713)WatchGpusResponse(726-726)WatchGpusResponse(741-743)Gpu(159-169)Gpu(182-182)Gpu(197-199)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(47-62)
client-go/examples/controller-shim/main.go (7)
client-go/client/versioned/clientset.go (1)
New(95-99)client-go/informers/externalversions/device/interface.go (1)
New(37-39)client-go/informers/externalversions/device/v1alpha1/interface.go (1)
New(36-38)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/informers/externalversions/factory.go (1)
NewSharedInformerFactory(91-93)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
api/device/v1alpha1/zz_generated.conversion.go (3)
api/gen/go/device/v1alpha1/gpu.pb.go (21)
Gpu(159-169)Gpu(182-182)Gpu(197-199)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)Condition(380-398)Condition(411-411)Condition(426-428)GpuList(223-230)GpuList(243-243)GpuList(258-260)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)GpuStatus(325-333)GpuStatus(346-346)GpuStatus(361-363)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)api/device/v1alpha1/converter.go (4)
FromProtobufTypeMeta(107-112)FromProtobufTimestamp(123-128)FromProtobufListTypeMeta(115-120)ToProtobufTimestamp(131-133)
client-go/informers/externalversions/generic.go (1)
api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/config.go (1)
client-go/version/version.go (1)
UserAgent(28-35)
client-go/client/versioned/clientset.go (4)
client-go/client/versioned/typed/device/v1alpha1/device_client.go (6)
DeviceV1alpha1Interface(25-28)DeviceV1alpha1Client(31-34)NewForConfig(43-51)NewForConfigAndClient(55-60)NewForConfigOrDie(64-71)New(74-79)client-go/hack/overlays/client/versioned/clientset.go (5)
Clientset(17-19)NewForConfig(32-44)NewForConfigAndClient(48-65)NewForConfigOrDie(69-76)New(79-83)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(27-72)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (66)
client-go/hack/boilerplate_overlay.go.txt (1)
1-16: LGTM!The boilerplate header template is correctly formatted with the standard Apache 2.0 license, proper copyright year, and an appropriate "DO NOT EDIT" generation comment. This aligns with the overlay pattern introduced in the PR for consistent code generation.
event-exporter/pkg/transformer/cloudevents.go (1)
60-60: LGTM: String representation improves CloudEvent readability.The change from numeric enum to string representation (
event.RecommendedAction.String()) makes CloudEvent payloads more human-readable and aligns with the v1alpha1 GPU API design where RecommendedAction is represented as a string.client-go/examples/README.md (1)
1-38: LGTM: Clear and comprehensive example documentation.The README effectively documents the three integration patterns with appropriate complexity levels and provides clear prerequisites and setup instructions for local development.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
21-24: Verify: Nil ClientConn could cause NPE in tests.The
ClientConn()method returns a typed nil (*grpc.ClientConncast togrpc.ClientConnInterface). While the comment clearly states the fake uses ObjectTracker, any test code attempting to invoke methods on the returned interface will panic with a nil pointer dereference.This pattern follows standard client-go conventions where fake clients return nil for transport-layer interfaces. However, verify that all test code using this fake client avoids calling
ClientConn()or handles the nil case appropriately.Based on learnings, consider using
envtestfor controller testing scenarios instead of fake clients where a more realistic environment is beneficial.client-go/go.mod (1)
1-15: LGTM: Module structure follows best practices.The module declaration, replace directive for the local
apimodule, and dependency selection align with the coding guidelines for separate Go modules and Kubernetes client patterns.As per coding guidelines, the separate module structure with semantic import versioning and use of
client-gofor Kubernetes API interactions is appropriate.client-go/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
28-38: LGTM: Standard informer factory interfaces.The interface definitions follow established client-go patterns for informer factories, enabling proper informer lifecycle management and resource-specific informer creation.
As per coding guidelines, these interfaces support the preferred pattern of using informers over direct API calls for watching Kubernetes resources.
client-go/hack/overlays/client/versioned/integration_test.go (2)
64-129: LGTM!The Get, List, and Watch subtests are well-structured with proper timeout handling in the Watch test and clear assertions. Good use of
selectwith timeouts to avoid test hangs.
131-182: LGTM!The Informer and Lister sync test follows best practices: instantiating the informer before starting the factory, using
cache.WaitForCacheSynccorrectly, and polling for eventual consistency withwait.PollUntilContextTimeout.client-go/informers/externalversions/generic.go (1)
1-60: LGTM!This is generated code that correctly implements the
GenericInformerinterface and wires theForResourcemethod to handle thegpusresource under thedevice.nvidia.com/v1alpha1group version. The implementation aligns with theSchemeGroupVersiondefined inapi/device/v1alpha1/register.go.client-go/nvgrpc/config.go (2)
51-67: LGTM!The
Default()method follows a sensible defaulting chain: environment variable → default constant. Usinglogr.Discard()as the fallback logger is appropriate.
69-89: LGTM!The
Validate()method provides clear error messages with context.GetLogger()is appropriately defensive, returning a discard logger even ifDefault()wasn't called.client-go/nvgrpc/watcher_test.go (6)
31-58: LGTM!Well-structured test that verifies normal event flow through the watcher. Good pattern of closing the events channel to signal completion.
60-83: LGTM!Good edge case coverage verifying that unknown event types are silently ignored while subsequent valid events are processed correctly.
85-117: LGTM!Good table-driven test following coding guidelines. Correctly verifies that gRPC error codes are translated to appropriate
metav1.Statusresponses (e.g.,OutOfRange→StatusReasonExpiredwith HTTP 410).
119-151: LGTM!Correctly verifies that the stream terminates after the first error and the second error is never delivered. Good use of timeout to prevent test hangs.
153-176: LGTM!The test correctly verifies that
Stop()cancels the context and closes the result channel. The short sleep on line 159 is a pragmatic approach to allow the receive goroutine to start.
178-238: LGTM!Well-designed test doubles.
FakeSource.Close()correctly guards against double-close panics, andNext()properly prioritizes error injection over channel events.api/go.mod (1)
3-3: No issues to address. Go 1.25.0 and k8s.io/apimachinery v0.34.2 are valid, stable versions appropriate for production use.client-go/nvgrpc/watcher.go (2)
84-137: LGTM! Well-structured receive loop with proper event handling.The receive loop correctly:
- Handles EOF and cancellation as normal termination
- Maps event type strings to Kubernetes watch.EventType constants
- Processes ERROR events explicitly
- Provides detailed logging at appropriate verbosity levels
- Respects the done channel for clean shutdown
139-164: LGTM! Proper error-to-status conversion for informer compatibility.The
sendError()method correctly:
- Converts gRPC status to metav1.Status
- Maps
OutOfRangeandResourceExhaustedto HTTP 410 (Expired) withStatusReasonExpired, which triggers informer resync- Respects the done channel to avoid blocking on shutdown
This is critical for informer reliability.
client-go/informers/externalversions/factory.go (3)
122-144: LGTM! Safe concurrent Start() implementation.The
Start()method correctly:
- Checks
shuttingDownflag to prevent starting during shutdown- Tracks started informers to allow multiple calls
- Captures the loop variable in each goroutine
- Uses WaitGroup for proper lifecycle management
146-153: LGTM! Proper shutdown coordination.The
Shutdown()method correctly sets the flag under lock and waits for all goroutines to complete. The implementation allows multiple concurrent calls safely.
176-198: LGTM! Correct informer creation with per-type customization.The
InformerFor()method correctly:
- Returns existing informers for idempotency
- Applies per-type custom resync periods or falls back to default
- Applies the shared transform function
- Properly synchronizes access to shared state
event-exporter/pkg/transformer/cloudevents_test.go (1)
101-102: LGTM! Test correctly updated for API refactor.The test expectation correctly changed from the int32 protobuf enum value
pb.RecommendedAction_RESTART_VMto the string representation"RESTART_VM". This aligns with the PR's API changes whereGPUStatus.RecommendedActionis now a string field in the v1alpha1 internal types.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
9-27: LGTM! Clean stream adapter implementation.The
gpuStreamAdaptercorrectly:
- Wraps the gRPC stream client
- Implements the
Sourceinterface expected by the Watcher- Converts protobuf responses to internal runtime.Object via
FromProto- Returns event type strings and objects for downstream processing
- Properly closes the stream via
CloseSend()This adapter enables the nvgrpc Watcher to work with GPU watch streams.
client-go/examples/streaming-daemon/main.go (4)
36-46: LGTM! Proper initialization and configuration.The setup correctly:
- Initializes structured logging with stdr
- Reads configuration from environment variable with sensible default
- Uses standard Unix domain socket path for local gRPC connection
49-58: LGTM! Well-implemented interceptors for observability.The interceptors correctly:
tracingInterceptor: Injectsx-request-idmetadata for request tracingwatchMonitorInterceptor: Logs the start of watch streams for monitoringThese demonstrate proper custom interceptor usage for cross-cutting concerns.
68-82: LGTM! Proper connection and clientset initialization.The initialization correctly:
- Creates nvgrpc.Config with the target
- Establishes connection with custom dial options
- Defers connection cleanup
- Creates versioned clientset from the connection
- Handles initialization errors appropriately
This demonstrates the manual connection management pattern when fine-grained control over interceptors is needed.
97-143: LGTM! Robust watch event processing.The watch loop correctly:
- Establishes the watch with proper error handling
- Defers watcher cleanup
- Handles closed channel, error events, and unknown object types
- Uses
meta.IsStatusConditionTrueto derive GPU readiness from conditions- Respects context timeout for clean shutdown
- Provides informative logging at each step
This is a good reference implementation for processing watch events.
client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
25-40: LGTM!The fake client implementation follows standard Kubernetes client-go fake patterns. The
ClientConn()method returningnilis well-documented and appropriate for an in-memory fake that usesObjectTrackerinstead of actual gRPC connections.api/proto/device/v1alpha1/gpu.proto (1)
53-77: Well-designed resource structure.The Gpu and GpuList messages correctly follow the Kubernetes Resource Model pattern with proper metadata, spec, and status separation. The field numbering is consistent and the documentation is clear.
client-go/client/versioned/fake/clientset_generated.go (1)
39-65: LGTM!The
NewSimpleClientsetfunction correctly sets up the fake clientset with anObjectTracker, registers reactors for CRUD operations, and configures watch handling. The implementation follows established Kubernetes client-go fake patterns.client-go/client/versioned/scheme/register.go (1)
28-54: LGTM!The scheme registration follows standard Kubernetes client-go patterns. The exported
AddToSchemefunction enables scheme composition with other clientsets, and theinit()function properly registers the v1 group version and device types.api/device/v1alpha1/gpu_types.go (1)
21-70: Well-structured GPU type definitions.The type definitions correctly follow Kubernetes CRD conventions with proper embedding of
TypeMeta,ObjectMeta, andListMeta. The code-gen markers are appropriately configured for a non-namespaced, read-only resource.api/device/v1alpha1/zz_generated.deepcopy.go (1)
1-125: LGTM!The auto-generated deepcopy implementations correctly handle all fields including nested slices (
Items,Conditions) with proper nil checks and element-wise deep copying. The generated code aligns with the type definitions ingpu_types.go.client-go/examples/controller-shim/main.go (1)
120-142: LGTM on the reconciler implementation.The
GPUReconcileris cleanly implemented with proper error handling usingclient.IgnoreNotFound. TheSetupWithManagermethod correctly registers the controller for GPU resources.client-go/client/versioned/integration_test.go (7)
1-48: LGTM! Well-structured integration test setup.The test establishes an in-process gRPC server via bufconn, properly wires the mock GPU service, and sets up context with timeout for cancellation. The import organization and test scaffolding follow good patterns.
49-102: Get and List subtests look correct.The basic Get and List operations are properly tested with appropriate assertions on the returned data.
104-145: Watch flow test correctly validates initial snapshot and live events.The test properly consumes the initial ADDED event, triggers a MODIFIED event via the mock, and verifies the event type and resource version propagation.
147-198: Informer and Lister sync test validates cache synchronization.The test correctly uses
cache.WaitForCacheSyncandwait.PollUntilContextTimeoutto verify the informer cache updates with watch events.
200-268: Controller-runtime compatibility test validates cache integration.The test properly wires the controller-runtime cache with custom
NewInformerto inject the GPU informer, demonstrating seamless integration between the gRPC-backed clientset and controller-runtime patterns.
273-293: Mock server initialization is clean.The mock properly uses a buffered channel for watch events and initializes with seed GPU data.
295-353: Mock server implementations are thread-safe and well-structured.
GetGpuandListGpusproperly useRLockfor concurrent readsWatchGpuscorrectly sends initial snapshot before entering live event loop- Proper context cancellation handling in the watch loop
client-go/client/versioned/clientset.go (1)
1-99: LGTM! Clean clientset implementation following client-go patterns.The generated clientset correctly:
- Exposes a minimal
Interfacefor dependency injection- Uses shallow copies to prevent config mutation
- Provides appropriate constructor variants (
NewForConfig,NewForConfigAndClient,NewForConfigOrDie,New)- Validates nil inputs with descriptive error messages
api/Makefile (3)
19-57: Configuration section is well-organized.Good use of helper variables for string manipulation, clear module/version definitions, and robust GO_VERSION fallback logic.
93-107: Code generation workflow is properly structured.The
code-gentarget correctly chains dependencies and runsgo mod tidyto synchronize after generation.
191-202: go-install-tool macro is robust.Uses versioned symlinks to avoid re-downloading and properly sets
GOTOOLCHAINfor consistent tool installation.client-go/client/versioned/typed/device/v1alpha1/device_client.go (1)
1-89: LGTM! Well-designed device client implementation.The generated client correctly:
- Exposes
DeviceV1alpha1InterfacewithClientConn()andGPUsGetter- Provides nil-safe
ClientConn()method (lines 84-86)- Uses
logr.Discard()as sensible default when config isn't available- Follows shallow-copy pattern to prevent config mutation
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
9-73: LGTM! Overlay implementation matches expected pattern.The overlay provides the same interface and constructor patterns as the generated client, enabling custom gRPC logic injection.
client-go/Makefile (4)
19-84: Configuration section is well-organized and consistent with api/Makefile.Good use of shared patterns: string manipulation helpers, versioned tool management, and
yq-based version loading from.versions.yaml.
100-149: Code generation workflow properly orchestrates multi-tool pipeline.The
code-gentarget correctly chainsclient-gen → copy-overlays → lister-gen → informer-gen, ensuring overlays are applied before dependent generators run.
105-113: Build and test exclusions are appropriate.Excluding
/hack/overlays/,/examples/, and test-infrastructure paths from build/test ensures only production code is validated.
198-213: go-install-tool macro is consistent with api/Makefile.Uses versioned symlinks and
GOTOOLCHAINfor reproducible tool installation.api/device/v1alpha1/zz_generated.conversion.go (13)
23-33: LGTM!The condition conversion properly handles nil input, correctly converts the Status field to
v1.ConditionStatus, and uses the timestamp helper appropriately.
34-49: LGTM!The list conversion correctly handles nil input, properly preserves the distinction between nil and empty slices, and efficiently allocates the Items slice only when needed.
50-56: LGTM!The ListMeta conversion correctly extracts the ResourceVersion field with proper nil handling.
57-64: LGTM!The ObjectMeta conversion correctly extracts the Name and ResourceVersion fields with proper nil handling. The minimal field set aligns with the node-local gRPC API design.
65-71: LGTM!The Spec conversion correctly maps the
Uuidfield from protobuf to theUUIDfield in the internal type with proper nil handling.
72-84: LGTM!The Status conversion properly handles nil checks for both the source and the Conditions slice, preserves the nil vs. empty slice distinction, and correctly maps all fields.
85-91: LGTM!The conversion correctly transforms the internal GPU to protobuf format. TypeMeta is appropriately omitted from the protobuf message (it's reconstructed on the wire).
92-100: LGTM!The condition conversion correctly transforms the internal type to protobuf format, with proper type conversion for the Status field and correct timestamp helper usage.
101-115: LGTM!The list conversion properly handles nil input, preserves the nil vs. empty slice distinction, and correctly converts each item to protobuf format.
116-120: LGTM!The ListMeta conversion correctly extracts the ResourceVersion field and returns the protobuf message.
121-126: LGTM!The ObjectMeta conversion correctly extracts the Name and ResourceVersion fields for the protobuf message, consistent with the minimal metadata design.
127-131: LGTM!The Spec conversion correctly maps the
UUIDfield to the protobufUuidfield.
132-142: LGTM!The Status conversion properly handles the Conditions slice with nil checking, preserves the nil vs. empty distinction, and correctly maps all fields to protobuf format.
9b3add0 to
bc160e9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (16)
client-go/version/version.go (1)
22-23: Fix typo in comment.Line 23 contains "It i set" which should be "It is set".
🔎 Proposed fix
// GitVersion is the semantic version of the client. -// It i set at build time via -ldflags +// It is set at build time via -ldflags // e.g., -ldflags "-X 'github.com/nvidia/nvsentinel/client-go/version.GitVersion=v1.2.3'"client-go/go.mod (1)
3-3: Updategoversion to 1.25.5 (latest stable patch release).Line 3 specifies
go 1.25.0, but the latest patch is1.25.5, which includes security fixes released December 2, 2025 for crypto/x509 and other packages. Upgrade to pick up these critical updates.🔎 Proposed fix
-go 1.25.0 +go 1.25.5After updating, run
go mod tidyand verify your CI build/test pipeline passes.client-go/examples/basic-client/README.md (1)
12-12: Incorrect relative path to Fake Server.The path
../../fake-serveris incorrect. Since this README is inclient-go/examples/basic-client/, the fake server atclient-go/examples/fake-server/should be referenced as../fake-server.🔎 Proposed fix
-1. Ensure the [Fake Server](../../fake-server) is running. +1. Ensure the [Fake Server](../fake-server) is running..versions.yaml (1)
49-51: Verify goverter version exists.The specified
goverter: 'v1.9.2'may not be a valid release. The latest known stable version is v1.8.2. The Kubernetes code-generator tools (v0.34.2) are compatible with client-go v0.34.1.#!/bin/bash # Verify goverter releases curl -s https://api.github.com/repos/jmattheis/goverter/releases | jq '.[0:5] | .[] | {tag_name, published_at}'client-go/examples/streaming-daemon/README.md (1)
13-13: Incorrect relative path to Fake Server.Same issue as basic-client README—the path
../../fake-servershould be../fake-serverto correctly referenceclient-go/examples/fake-server/.🔎 Proposed fix
-1. Ensure the [Fake Server](../../fake-server) is running. +1. Ensure the [Fake Server](../fake-server) is running.client-go/examples/controller-shim/main.go (2)
58-62: The informer factory is never started.The comment on line 60 states the Manager will start the injected informer, but controller-runtime only starts informers created through its own cache machinery. The
factory.Start()must be called explicitly for the gRPC-backed informer to populate its cache.🔎 Proposed fix
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + // Start the factory before creating the manager. The informer must be running + // and synced before the manager attempts to use the cache. + stopCh := make(chan struct{}) + go factory.Start(stopCh) + factory.WaitForCacheSync(stopCh)Note: Ensure
stopChis closed on shutdown (e.g., viadefer close(stopCh)after signal handling setup, or tie toctx.Done()).
78-96: Returningnilfor non-GPU objects may cause panics.When
NewInformerreturnsnil(line 95) for objects other than*devicev1alpha1.GPU, controller-runtime may attempt to use the nil informer, leading to nil pointer dereferences. Return a default informer for unhandled types.🔎 Proposed fix
NewInformer: func(lw toolscache.ListerWatcher, obj runtime.Object, resync time.Duration, indexers toolscache.Indexers) toolscache.SharedIndexInformer { if _, ok := obj.(*devicev1alpha1.GPU); ok { // ... existing GPU handling ... return gpuInformer } - return nil + // Fall back to the default informer for non-GPU objects. + return toolscache.NewSharedIndexInformer(lw, obj, resync, indexers) },api/Makefile (2)
128-128: Undefined variableAPI_PKGS_COMMAwill cause build failure.Line 128 references
API_PKGS_COMMA, but this variable is not defined anywhere in the Makefile. OnlyAPI_VERSIONS_COMMA(line 31) andAPI_PKGS(line 34) are defined. This will pass an empty string to--bounding-dirs, causingdeepcopy-gento fail or behave incorrectly.🔎 Proposed fix
Add the missing variable definition after line 34:
# Helper for tools that need full package paths API_PKGS := $(foreach version,$(API_VERSIONS),$(MODULE_NAME)/$(version)) + +# Helper for tools that need comma-separated package paths +API_PKGS_COMMA := $(subst $(SPACE),$(COMMA),$(API_PKGS))
134-134: Minor typo: double period in help text.🔎 Proposed fix
-conversion-gen: $(GOVERTER) clean-conversion ## Generate conversion code.. +conversion-gen: $(GOVERTER) clean-conversion ## Generate conversion code.api/proto/device/v1alpha1/gpu.proto (1)
27-51: Inconsistent indentation in comments (duplicate finding).Lines 35-37 and 47-48 use tabs while surrounding lines use spaces. This was already flagged in a previous review.
client-go/hack/overlays/client/versioned/integration_test.go (1)
210-214: Avoid callingt.Errorffrom a goroutine.This is still a race condition risk. Calling
t.Errorffrom within a goroutine is unsafe and can cause races or panics if the test completes before the goroutine executes.client-go/client/versioned/integration_test.go (1)
226-230: Goroutine error won't fail the test.
t.Errorfcalled from within a goroutine won't properly fail the test. This is the same issue flagged previously.client-go/examples/fake-server/main.go (1)
185-193:ListMetais not populated in the response.The
GpuListresponse doesn't includemetadata.resource_version, which is needed for clients to establish a watch from a consistent point (List-then-Watch pattern). This was flagged in a previous review.client-go/nvgrpc/watcher.go (1)
64-77: Potential race condition inStop()with double-close protection.The
selecton lines 72-76 attempts to prevent double-close ofw.done, but there's a race window between checking and closing. Additionally,receive()callsdefer w.Stop()(line 90), which could race with an externalStop()call. This was flagged in a previous review - consider usingsync.Oncefor safer shutdown.api/device/v1alpha1/converter.go (1)
106-120:APIVersionshould include the group, not just the version.The Kubernetes
TypeMeta.APIVersionfield should be in the formatgroup/version. UsingSchemeGroupVersion.Versionproduces onlyv1alpha1, but the correct value should bedevice.nvidia.com/v1alpha1. UseSchemeGroupVersion.String()instead.func FromProtobufTypeMeta(_ *pb.Gpu) metav1.TypeMeta { return metav1.TypeMeta{ Kind: "GPU", - APIVersion: SchemeGroupVersion.Version, + APIVersion: SchemeGroupVersion.String(), } } func FromProtobufListTypeMeta(_ *pb.GpuList) metav1.TypeMeta { return metav1.TypeMeta{ Kind: "GPUList", - APIVersion: SchemeGroupVersion.Version, + APIVersion: SchemeGroupVersion.String(), } }client-go/informers/externalversions/factory.go (1)
200-224: Documentation references non-existent method.The example references
factory.WaitForStop()on line 208, but the actual method isShutdown(). Since this is generated code, this should be fixed in the generator template.
🧹 Nitpick comments (19)
client-go/nvgrpc/config_test.go (3)
20-59: Use testify assertions per coding guidelines.The test logic is correct and follows table-driven test patterns well. However, per the coding guidelines, Go tests should use
testify/assertortestify/requirefor assertions instead of basict.Errorf.🔎 Proposed refactor using testify/assert
import ( "testing" + + "github.com/stretchr/testify/assert" ) func TestConfig_Default_TargetPrecedence(t *testing.T) { tests := []struct { name string argTarget string envTarget string wantTarget string }{ { name: "Explicit target is preserved", argTarget: "unix:///arg.sock", envTarget: "unix:///env.sock", wantTarget: "unix:///arg.sock", }, { name: "Env var used when target is empty", argTarget: "", envTarget: "unix:///env.sock", wantTarget: "unix:///env.sock", }, { name: "Default used when both are empty", argTarget: "", envTarget: "", wantTarget: DefaultNvidiaDeviceAPISocket, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Setenv(NvidiaDeviceAPITargetEnvVar, tt.envTarget) cfg := &Config{Target: tt.argTarget} cfg.Default() - if cfg.Target != tt.wantTarget { - t.Errorf("Target = %q, want %q", cfg.Target, tt.wantTarget) - } + assert.Equal(t, tt.wantTarget, cfg.Target) }) } }As per coding guidelines for
**/*_test.go.
61-80: Use testify assertions and validate the actual default UserAgent value.The test correctly validates preservation of custom UserAgent, but the first subtest only checks that UserAgent is non-empty rather than validating it matches the expected default from
version.UserAgent(). Additionally, per coding guidelines, usetestify/assertfor assertions.🔎 Proposed refactor with testify and explicit default validation
import ( "testing" + + "github.com/stretchr/testify/assert" + "github.com/nvidia/nvidia-device-api/client-go/version" ) func TestConfig_Default_UserAgent(t *testing.T) { t.Run("Populates default UserAgent if empty", func(t *testing.T) { cfg := &Config{} cfg.Default() - if cfg.UserAgent == "" { - t.Error("UserAgent should have been populated with version-based default") - } + assert.Equal(t, version.UserAgent(), cfg.UserAgent) }) t.Run("Preserves custom UserAgent", func(t *testing.T) { custom := "my-custom-agent/1.0" cfg := &Config{UserAgent: custom} cfg.Default() - if cfg.UserAgent != custom { - t.Errorf("UserAgent = %q, want %q", cfg.UserAgent, custom) - } + assert.Equal(t, custom, cfg.UserAgent) }) }As per coding guidelines for
**/*_test.go.
82-120: Use testify assertions per coding guidelines.The validation test logic is correct and provides good coverage of both valid and invalid configurations. However, per the coding guidelines, Go tests should use
testify/assertortestify/requirefor assertions.🔎 Proposed refactor using testify/assert
import ( "testing" + + "github.com/stretchr/testify/assert" ) func TestConfig_Validate(t *testing.T) { tests := []struct { name string cfg Config wantErr bool }{ { name: "Valid config", cfg: Config{ Target: "unix:///var/run/test.sock", UserAgent: "test/1.0", }, wantErr: false, }, { name: "Missing target", cfg: Config{ UserAgent: "test/1.0", }, wantErr: true, }, { name: "Missing user agent", cfg: Config{ Target: "unix:///var/run/test.sock", }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.cfg.Validate() - if (err != nil) != tt.wantErr { - t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) - } + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } }) } }As per coding guidelines for
**/*_test.go.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
17-24: Consider clarifying typed nil behavior or improving implementation.The method returns a typed nil pointer (
*grpc.ClientConn) asgrpc.ClientConnInterface. This creates an interface value that is non-nil (due to containing type information) but holds a nil pointer—a common Go interface gotcha that can confuse callers checkingconn != nil.While the comment documents that fakes use ObjectTracker rather than gRPC, consider one of these alternatives for clarity:
- Explicitly document that callers should not invoke
ClientConn()on fakes- Return a stub that panics with a clear message if any gRPC method is invoked
- Add a comment warning about the nil pointer behavior
💡 Alternative: panic on usage
// ClientConn returns a ClientConn that is used to communicate // with gRPC server by this client implementation. // -// Note: the Fake implementation uses the ObjectTracker memory store, not an actual gRPC connection. +// Note: the Fake implementation uses the ObjectTracker memory store, not an actual gRPC connection. +// Calling this method on a fake client is not supported and will return a nil connection. func (c *FakeDeviceV1alpha1) ClientConn() grpc.ClientConnInterface { - var ret *grpc.ClientConn - return ret + // Returning typed nil to satisfy interface contract. + // Callers should not use ClientConn on fake implementations. + return (*grpc.ClientConn)(nil) }Or alternatively, panic explicitly:
func (c *FakeDeviceV1alpha1) ClientConn() grpc.ClientConnInterface { - var ret *grpc.ClientConn - return ret + panic("ClientConn() should not be called on fake client implementations") }client-go/DEVELOPMENT.md (2)
10-11: Minor: Fix list indentation for markdown consistency.Static analysis flags inconsistent indentation (4 spaces instead of 2) for nested list items.
🔎 Proposed fix
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)
77-77: Nitpick: Remove redundant phrasing."inside of" can be simplified to "inside" for conciseness.
🔎 Proposed fix
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.client-go/Makefile (1)
187-187: Declaretoolstarget as PHONY.The
toolstarget should be marked.PHONYfor consistency with other non-file-generating targets in this Makefile.🔎 Proposed fix
Add before line 187:
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)Based on static analysis hint from checkmake.
client-go/nvgrpc/options_test.go (1)
48-64: Consider using testify assertions for consistency.The test uses manual error checks with
t.Errorf. Per coding guidelines, prefertestify/assertortestify/requirefor assertions in Go tests.🔎 Proposed refactor using testify
import ( "context" "testing" "github.com/go-logr/logr" + "github.com/stretchr/testify/assert" "google.golang.org/grpc" )Then update the assertions:
t.Run("Logger is correctly assigned", func(t *testing.T) { - if dOpts.logger != testLogger { - t.Errorf("expected logger to be set, got %v", dOpts.logger) - } + assert.Equal(t, testLogger, dOpts.logger, "logger should be set correctly") }) t.Run("Unary interceptors are correctly appended", func(t *testing.T) { - if len(dOpts.unaryInterceptors) != 2 { - t.Errorf("expected 2 unary interceptors, got %d", len(dOpts.unaryInterceptors)) - } + assert.Len(t, dOpts.unaryInterceptors, 2, "should have 2 unary interceptors") }) t.Run("Stream interceptors are correctly appended", func(t *testing.T) { - if len(dOpts.streamInterceptors) != 2 { - t.Errorf("expected 2 stream interceptors, got %d", len(dOpts.streamInterceptors)) - } + assert.Len(t, dOpts.streamInterceptors, 2, "should have 2 stream interceptors") })As per coding guidelines for Go tests.
client-go/nvgrpc/interceptors_test.go (2)
29-66: Consider using testify assertions for better test output.The tests currently use
t.Fatalffor assertions. Per coding guidelines, prefertestify/assertortestify/requirefor more informative failure messages and better test maintainability.🔎 Refactor to use testify/require
import ( "context" "errors" "testing" "time" logr "github.com/go-logr/logr/testing" + "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" )err := interceptor(context.Background(), tt.method, nil, nil, nil, invoker) - if !errors.Is(err, tt.invokerErr) { - t.Fatalf("Returned error mismatch. Got %v, want %v", err, tt.invokerErr) - } + require.ErrorIs(t, err, tt.invokerErr, "Returned error should match invoker error") }) } }
68-103: Consider using testify assertions for better test output.Same as the unary test, prefer
testify/requirefor more descriptive assertion failures.🔎 Refactor to use testify/require
_, err := interceptor(context.Background(), desc, nil, tt.method, streamer) - if !errors.Is(err, tt.streamerErr) { - t.Fatalf("Returned error mismatch. Got %v, want %v", err, tt.streamerErr) - } + require.ErrorIs(t, err, tt.streamerErr, "Returned error should match streamer error") }) } }client-go/hack/overlays/client/versioned/clientset.go (1)
1-10: Missing package-level godoc comment.Per coding guidelines, package-level godoc is required for all Go packages. Consider adding a doc comment describing this package's purpose.
+// Package versioned provides the versioned clientset for the NVIDIA Device API, +// enabling gRPC-based access to GPU resources using Kubernetes-native patterns. package versionedclient-go/hack/overlays/client/versioned/integration_test.go (1)
64-86: Consider using testify for assertions.Per coding guidelines,
testify/assertandtestify/requireare preferred for assertions in Go tests. This would improve readability and provide better error messages.Example refactor for Get subtest
+import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) t.Run("Get", func(t *testing.T) { gpu, err := cs.DeviceV1alpha1().GPUs().Get(ctx, "gpu-1", metav1.GetOptions{}) - if err != nil { - t.Fatalf("Get failed: %v", err) - } - if gpu.Name != "gpu-1" { - t.Errorf("Expected gpu-1, got %s", gpu.Name) - } + require.NoError(t, err, "Get failed") + assert.Equal(t, "gpu-1", gpu.Name) })client-go/client/versioned/integration_test.go (1)
271-353: Consider extracting shared test utilities.The
mockGpuServerimplementation and test patterns are nearly identical toclient-go/hack/overlays/client/versioned/integration_test.go. Consider extracting the mock server and common test helpers into a shared internal test package to reduce duplication.client-go/examples/fake-server/main.go (2)
40-41: Consider using structured logging.Per coding guidelines,
log/slogis preferred for structured logging in Go code. While simpler logging may suffice for an example server, structured logs would better demonstrate production patterns.Example using slog
import "log/slog" // In main() slog.Info("Starting server") slog.Info("Fake Device API listening", "socketPath", socketPath) // In WatchGpus slog.Info("Watch stream connected") slog.Info("Watch stream disconnected")Also applies to: 228-234
157-166: Non-blocking broadcast silently drops events.The
select/defaultpattern prevents deadlock but silently drops events when channels are full. This is fine for a fake server, but consider adding a debug log when events are dropped to aid troubleshooting.select { case ch <- gpu: default: + // Event dropped - listener channel full }api/device/v1alpha1/gpu_types.go (1)
15-19: Missing package-level godoc comment.Per coding guidelines, package-level godoc is required. Consider adding documentation for this API package.
+// Package v1alpha1 contains API types for the NVIDIA Device API v1alpha1 version. +// It defines the GPU resource type and related specifications for representing +// GPU devices in a Kubernetes-native way. package v1alpha1client-go/nvgrpc/watcher.go (1)
106-121: Consider adding BOOKMARK event type support.Kubernetes informers use BOOKMARK events for watch progress updates. If the gRPC service may send bookmark events, consider handling them:
+case "BOOKMARK": + eventType = watch.Bookmark case "ERROR":If bookmarks aren't part of your protocol, this can be deferred.
client-go/informers/externalversions/generic.go (1)
50-50: Address the TODO comment.The TODO indicates plans to extend generic informer support to unknown resources with a client pool. Consider tracking this as a feature request.
Do you want me to open a new issue to track this enhancement?
client-go/nvgrpc/watcher_test.go (1)
159-159: Consider removing the sleep.The
time.Sleep(10 * time.Millisecond)is used to allow the receive loop to start, but this introduces timing dependencies. Consider if synchronization primitives or test helpers could eliminate this sleep.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**api/go.sumis excluded by!**/*.sumclient-go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (71)
.gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/device/v1alpha1/zz_generated.conversion.go(1 hunks)api/device/v1alpha1/zz_generated.deepcopy.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/client/versioned/clientset.go(1 hunks)client-go/client/versioned/fake/clientset_generated.go(1 hunks)client-go/client/versioned/fake/doc.go(1 hunks)client-go/client/versioned/fake/register.go(1 hunks)client-go/client/versioned/integration_test.go(1 hunks)client-go/client/versioned/scheme/doc.go(1 hunks)client-go/client/versioned/scheme/register.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/generated_expansion.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/informers/externalversions/device/interface.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/gpu.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/interface.go(1 hunks)client-go/informers/externalversions/factory.go(1 hunks)client-go/informers/externalversions/generic.go(1 hunks)client-go/informers/externalversions/internalinterfaces/factory_interfaces.go(1 hunks)client-go/listers/device/v1alpha1/expansion_generated.go(1 hunks)client-go/listers/device/v1alpha1/gpu.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- client-go/hack/boilerplate.go.txt
- api/hack/boilerplate.go.txt
🚧 Files skipped from review as they are similar to previous changes (30)
- client-go/examples/basic-client/main.go
- client-go/hack/apply-overlays.sh
- client-go/client/versioned/scheme/register.go
- client-go/client/versioned/fake/doc.go
- client-go/hack/boilerplate_overlay.go.txt
- client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
- client-go/informers/externalversions/device/v1alpha1/gpu.go
- client-go/nvgrpc/client_conn_test.go
- api/device/v1alpha1/gpu_conversion_test.go
- .gitignore
- client-go/examples/controller-shim/README.md
- api/go.mod
- client-go/examples/fake-server/README.md
- client-go/client/versioned/typed/device/v1alpha1/gpu.go
- client-go/informers/externalversions/device/interface.go
- client-go/informers/externalversions/device/v1alpha1/interface.go
- client-go/version/version_test.go
- client-go/client/versioned/clientset.go
- client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
- api/device/v1alpha1/zz_generated.deepcopy.go
- client-go/client/versioned/typed/device/v1alpha1/doc.go
- client-go/nvgrpc/config.go
- client-go/client/versioned/typed/device/v1alpha1/device_client.go
- client-go/nvgrpc/client_conn.go
- client-go/client/versioned/typed/device/v1alpha1/fake/doc.go
- client-go/README.md
- client-go/client/versioned/fake/clientset_generated.go
- client-go/client/versioned/scheme/doc.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/client/versioned/typed/device/v1alpha1/generated_expansion.goclient-go/nvgrpc/options_test.goclient-go/listers/device/v1alpha1/gpu.goclient-go/client/versioned/fake/register.goclient-go/examples/streaming-daemon/main.goapi/device/v1alpha1/doc.goapi/device/v1alpha1/gpu_conversion.goclient-go/nvgrpc/config_test.goclient-go/version/version.goclient-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/nvgrpc/interceptors.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/informers/externalversions/generic.goapi/device/v1alpha1/gpu_types.goapi/device/v1alpha1/converter.goclient-go/informers/externalversions/factory.goclient-go/nvgrpc/watcher_test.goapi/device/v1alpha1/register.goclient-go/listers/device/v1alpha1/expansion_generated.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/nvgrpc/watcher.goclient-go/examples/controller-shim/main.goclient-go/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/options.goapi/device/v1alpha1/zz_generated.conversion.goclient-go/nvgrpc/interceptors_test.goclient-go/examples/fake-server/main.goclient-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/options_test.goclient-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.goclient-go/client/versioned/integration_test.goclient-go/nvgrpc/interceptors_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
client-go/go.mod
🧠 Learnings (15)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/examples/basic-client/README.mdclient-go/version/version.goclient-go/go.mod.versions.yamlclient-go/examples/README.mdclient-go/DEVELOPMENT.mdclient-go/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/version/version.goclient-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Extract informer event handler setup into helper methods
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.goclient-go/informers/externalversions/factory.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/informers/externalversions/generic.goclient-go/go.modclient-go/informers/externalversions/factory.goclient-go/nvgrpc/watcher.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/go.mod.versions.yamlclient-go/examples/README.mdclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/informers/externalversions/factory.goclient-go/nvgrpc/watcher.goclient-go/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
client-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
client-go/go.mod.versions.yamlapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `testify/assert` and `testify/require` for assertions in Go tests
Applied to files:
client-go/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/client/versioned/integration_test.go
🧬 Code graph analysis (12)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
client-go/listers/device/v1alpha1/gpu.go (3)
api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)client-go/listers/device/v1alpha1/expansion_generated.go (1)
GPUListerExpansion(21-21)api/device/v1alpha1/register.go (1)
Resource(25-27)
client-go/client/versioned/fake/register.go (2)
api/device/v1alpha1/register.go (2)
SchemeBuilder(31-31)AddToScheme(34-34)client-go/client/versioned/scheme/register.go (1)
AddToScheme(49-49)
client-go/nvgrpc/config_test.go (2)
client-go/nvgrpc/config.go (3)
DefaultNvidiaDeviceAPISocket(31-31)NvidiaDeviceAPITargetEnvVar(28-28)Config(41-49)client-go/version/version.go (1)
UserAgent(28-35)
api/device/v1alpha1/converter.go (3)
api/gen/go/device/v1alpha1/gpu.pb.go (21)
Gpu(159-169)Gpu(182-182)Gpu(197-199)GpuList(223-230)GpuList(243-243)GpuList(258-260)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)GpuSpec(277-285)GpuSpec(298-298)GpuSpec(313-315)GpuStatus(325-333)GpuStatus(346-346)GpuStatus(361-363)Condition(380-398)Condition(411-411)Condition(426-428)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(47-62)
api/device/v1alpha1/register.go (3)
client-go/client/versioned/fake/register.go (1)
AddToScheme(49-49)client-go/client/versioned/scheme/register.go (2)
AddToScheme(49-49)Scheme(28-28)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
client-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(38-43)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/examples/controller-shim/main.go (9)
client-go/client/versioned/clientset.go (1)
New(95-99)client-go/client/versioned/typed/device/v1alpha1/device_client.go (1)
New(74-79)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
New(58-63)client-go/informers/externalversions/device/interface.go (1)
New(37-39)client-go/informers/externalversions/device/v1alpha1/interface.go (1)
New(36-38)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/informers/externalversions/factory.go (1)
NewSharedInformerFactory(91-93)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/nvgrpc/interceptors_test.go (1)
client-go/nvgrpc/interceptors.go (2)
NewLatencyUnaryInterceptor(28-59)NewLatencyStreamInterceptor(62-92)
client-go/examples/fake-server/main.go (3)
api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/gen/go/device/v1alpha1/gpu.pb.go (12)
ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)Condition(380-398)Condition(411-411)Condition(426-428)Gpu(159-169)Gpu(182-182)Gpu(197-199)WatchGpusResponse(696-713)WatchGpusResponse(726-726)WatchGpusResponse(741-743)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go (7)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
FakeDeviceV1alpha1(25-27)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
FakeDeviceV1alpha1(9-11)client-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(38-43)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)api/gen/go/device/v1alpha1/gpu.pb.go (3)
ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (52)
client-go/client/versioned/typed/device/v1alpha1/generated_expansion.go (1)
1-19: LGTM!Standard client-gen expansion interface pattern. The empty
GPUExpansioninterface provides an extension point for custom methods without modifying generated code.client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go (1)
25-46: LGTM!Generated fake client correctly implements
GPUInterfaceusinggentype.FakeClientWithList. The resource metadata (gpus,GPUkind) aligns with the API definitions, and the list/pointer conversion helpers follow the standard client-gen patterns.client-go/examples/controller-shim/main.go (2)
40-56: LGTM on client initialization.The gRPC-backed clientset setup follows the established patterns. Environment variable fallback for the target endpoint and proper error handling are implemented correctly. As per coding guidelines,
client-gois used appropriately for Kubernetes API interactions.
120-142: LGTM on GPUReconciler implementation.The reconciler follows best practices:
- Uses
client.IgnoreNotFoundfor graceful handling of deleted resources.- Structured logging via
ctrl.LoggerFrom(ctx).SetupWithManageris properly extracted as a helper method per coding guidelines.api/device/v1alpha1/doc.go (1)
1-19: LGTM!The package documentation and Kubebuilder annotation are properly structured for code generation. The
+groupNamemarker correctly identifies the API group.client-go/listers/device/v1alpha1/expansion_generated.go (1)
19-21: LGTM!Standard Kubernetes code-generator expansion pattern. The empty
GPUListerExpansioninterface enables downstream augmentation ofGPUListerwithout modifying generated code.client-go/client/versioned/fake/register.go (1)
28-54: LGTM!The fake scheme registration follows standard Kubernetes client-go patterns. The initialization sequence correctly registers metav1 core types and device.nvidia.com/v1alpha1 types into the fake clientset's scheme.
api/device/v1alpha1/register.go (1)
23-44: LGTM!The API registration correctly follows Kubernetes conventions. The
SchemeGroupVersion,SchemeBuilder, andaddKnownTypesproperly registerGPUandGPUListtypes for thedevice.nvidia.com/v1alpha1group.client-go/examples/streaming-daemon/main.go (4)
36-45: LGTM!Logger initialization and environment-based configuration are appropriate for an example program.
47-58: LGTM!Custom interceptors effectively demonstrate how to extend gRPC client behavior with metadata injection and logging.
60-94: LGTM!Client initialization and List operation demonstrate proper error handling, resource cleanup with defer, and timeout management.
96-143: LGTM! Example demonstrates watch stream patterns well.The watch implementation shows proper error handling, type assertions, and timeout management. For production use, consider adding signal handling (SIGTERM/SIGINT) for graceful shutdown, but this is appropriate for an example program.
client-go/listers/device/v1alpha1/gpu.go (1)
26-46: LGTM!Generated lister code follows standard Kubernetes client-gen patterns and correctly integrates with the GPU resource type.
client-go/nvgrpc/interceptors.go (2)
27-59: LGTM!Interceptor correctly measures latency, applies appropriate log levels based on error types, and preserves original error propagation.
61-92: LGTM!Stream interceptor follows consistent patterns with the unary interceptor and correctly handles stream establishment latency tracking.
api/device/v1alpha1/gpu_conversion.go (4)
24-32: LGTM!Proper nil handling and delegation to the generated converter implementation.
34-40: LGTM!Correct nil handling and dereferencing for the protobuf conversion.
42-48: LGTM!Proper nil handling for list conversion.
50-56: LGTM!Correct nil handling and dereferencing for list conversion.
client-go/informers/externalversions/internalinterfaces/factory_interfaces.go (1)
28-38: LGTM!Generated informer interfaces follow standard Kubernetes informer-gen patterns and align with retrieved learnings about informer usage.
Based on learnings, these interfaces support the pattern of using informers over direct API calls and enable proper informer factory management.
client-go/nvgrpc/options.go (2)
22-29: LGTM!Functional options pattern is correctly implemented with an unexported options struct and exported option type.
31-50: LGTM!Option configurators correctly implement composition for interceptors (append) and replacement for logger (assignment), which is the expected behavior for these types of options.
api/proto/device/v1alpha1/gpu.proto (2)
53-70: LGTM!Gpu message structure follows Kubernetes resource patterns with proper metadata, spec, and status separation. Field numbering is stable and comments are comprehensive.
72-167: LGTM! Metadata additions enable Kubernetes-native semantics.The addition of ListMeta and resource_version fields to GpuList, ListGpusRequest, and WatchGpusRequest enables versioned listing and watch operations consistent with Kubernetes API patterns. The breaking change to GpuList field numbering (items from 1→2) is appropriately flagged in the PR objectives.
client-go/hack/overlays/client/versioned/clientset.go (1)
26-83: LGTM!The constructor functions follow standard client-go patterns with proper nil validation, defensive shallow copying to prevent config mutation, and clear error messages. The
NewForConfigOrDiepattern matches Kubernetes conventions.client-go/hack/overlays/client/versioned/integration_test.go (1)
257-337: LGTM!The mock server implementation is well-structured with proper thread-safety via
sync.RWMutex, clean context cancellation handling inWatchGpus, and an appropriate channel-based event delivery mechanism for testing watch flows.client-go/examples/fake-server/main.go (1)
68-76: LGTM for signal handling.The graceful shutdown handling correctly stops the gRPC server and cleans up the socket file on SIGINT/SIGTERM.
api/device/v1alpha1/gpu_types.go (1)
47-61: LGTM!The GPU type is well-defined with proper Kubernetes API conventions. The genclient markers correctly indicate this is a cluster-scoped, read-only resource with get/list/watch verbs, which aligns with the PR's goal of exposing GPU state without mutation capabilities.
client-go/nvgrpc/watcher.go (1)
139-163: LGTM!The error-to-status mapping correctly translates gRPC error codes to Kubernetes status responses. The special handling for
OutOfRangeandResourceExhausted→ 410 Expired is critical for triggering informer relist behavior, and the inline comment documents this well.api/device/v1alpha1/converter.go (2)
23-104: LGTM!The Converter interface is well-structured with comprehensive goverter annotations. The bidirectional mappings between protobuf and Kubernetes types are complete, and the
goverter:ignoredirectives appropriately handle Kubernetes-specific fields not present in the protobuf definitions.
122-133: LGTM!The timestamp conversion helpers correctly handle nil protobuf timestamps and properly convert between
metav1.Timeandtimestamppb.Timestamp.client-go/informers/externalversions/generic.go (2)
27-37: LGTM!The GenericInformer interface and genericInformer struct follow standard client-go patterns for generic informer access.
39-47: LGTM!The Informer and Lister methods correctly implement the GenericInformer interface using standard client-go patterns.
client-go/nvgrpc/watcher_test.go (5)
31-58: LGTM!The test correctly validates the normal event flow (ADDED, MODIFIED, DELETED) and verifies event types.
60-83: LGTM!The test correctly validates that UNKNOWN event types are ignored and subsequent ADDED events are processed.
85-117: LGTM!The table-driven test correctly validates error propagation and metav1.Status formatting for different gRPC error codes.
119-151: LGTM!The test correctly validates that errors terminate the stream and includes appropriate timeout handling to prevent test hangs.
178-238: LGTM!The test helpers (FakeObject, FakeSource) are well-implemented with proper nil-safety, idempotent Close(), and correct runtime.Object implementation.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (5)
9-18: LGTM!The DeviceV1alpha1Interface and DeviceV1alpha1Client follow standard client-go patterns for versioned clients.
20-22: LGTM!The GPUs() method correctly returns a GPUInterface using the standard factory pattern.
24-35: LGTM!The NewForConfig constructor correctly creates a shallow copy of the config to prevent mutation and properly handles errors.
37-55: LGTM!The constructors follow standard Kubernetes client patterns, with NewForConfigOrDie appropriately using panic for fatal configuration errors.
57-73: LGTM!The New() constructor appropriately uses a discarded logger, and ClientConn() includes proper nil-safety checks.
api/device/v1alpha1/zz_generated.conversion.go (2)
11-84: LGTM!The FromProtobuf* conversion methods correctly implement nil-safety and proper slice handling for conversions from protobuf to internal Go types.
85-142: LGTM!The ToProtobuf* conversion methods correctly implement conversions from internal Go types to protobuf, with appropriate nil-safety for pointer receivers.
client-go/informers/externalversions/factory.go (7)
33-88: LGTM!The functional options (WithCustomResyncConfig, WithTweakListOptions, WithNamespace, WithTransform) follow the standard functional options pattern correctly.
90-120: LGTM!The factory constructors are correctly implemented, with appropriate deprecation notices and functional option application.
122-144: LGTM!The Start method correctly implements safe multi-call semantics with proper loop variable capture, WaitGroup tracking, and shutdown flag checking.
146-153: LGTM!The Shutdown method correctly sets the shutdown flag under lock and waits for all goroutines to complete.
155-174: LGTM!WaitForCacheSync correctly minimizes lock contention by copying the informers map and only waits for informers that have been started.
176-198: LGTM!InformerFor correctly implements lazy initialization with proper locking, per-type resync configuration, and transform application.
258-260: LGTM!The Device() method correctly returns a device.Interface with appropriate namespace and tweak options.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
Outdated
Show resolved
Hide resolved
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
Outdated
Show resolved
Hide resolved
bc160e9 to
1776d86
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (9)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-1: Add package-level godoc comment.The coding guidelines require package-level documentation for all Go packages. A past review comment already flagged this missing documentation.
As per coding guidelines.
🔎 Suggested documentation
+// Package fake provides fake implementations of the device v1alpha1 client +// for testing purposes. These fakes use an in-memory ObjectTracker instead +// of actual gRPC connections. package fake
13-15: Add function comment for exported method.The coding guidelines require function comments for all exported Go functions. A past review comment already flagged this missing documentation.
As per coding guidelines.
🔎 Suggested documentation
+// GPUs returns a fake GPUInterface for testing GPU operations +// without requiring an actual gRPC connection. func (c *FakeDeviceV1alpha1) GPUs() v1alpha1.GPUInterface { return newFakeGPUs(c) }api/proto/device/v1alpha1/gpu.proto (1)
27-51: Metadata types align with Kubernetes conventions.The ObjectMeta and ListMeta messages follow Kubernetes API patterns correctly, with appropriate field documentation explaining the opaque, read-only nature of resource_version.
Note: The indentation inconsistency in comments (lines 35-37, 47-48) has already been flagged in a previous review.
client-go/hack/overlays/client/versioned/integration_test.go (1)
210-214: Avoid callingt.Errorffrom a goroutine.As previously noted, calling
t.Errorf(or anytmethod) from a goroutine is unsafe and can cause race conditions. Use an error channel to communicate errors back to the main test goroutine.client-go/examples/controller-shim/main.go (1)
58-62: The informer factory is never started.The comment on Line 60 states the Manager will start the injected informer, but controller-runtime only starts informers created through its own cache machinery. The gRPC-backed informer from
factoryneeds to be started explicitly; otherwise, the cache will never populate and reconciliation won't occur.🔎 Proposed fix
Start the factory before starting the manager:
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + + // Start the factory to populate the gRPC-backed informer cache. + // The manager's lifecycle context will handle shutdown. + ctx := ctrl.SetupSignalHandler() + go factory.Start(ctx.Done()) + + // Wait for the informer cache to sync before starting the manager. + if !cache.WaitForCacheSync(ctx.Done(), gpuInformer.HasSynced) { + setupLog.Error(nil, "failed to sync informer cache") + os.Exit(1) + } // Initialize the controller-runtime Manager.Then update the manager initialization to use the already-created
ctx:- ctx := ctrl.SetupSignalHandler() - setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil {client-go/client/versioned/integration_test.go (2)
15-15: Misleading "DO NOT EDIT" header for a manually maintained test file.This test file contains substantial manual test logic (mock server, test cases, assertions). The "Code generated... DO NOT EDIT" comment may confuse maintainers about whether modifications are allowed.
🔎 Proposed fix
Replace with a clear header:
-// Code generated by client-gen and gRPC overlay. DO NOT EDIT. +// Integration test - manually maintained. Changes permitted.
226-230: Goroutine error won't fail the test reliably.
t.Errorfcalled from within a goroutine will log the error but won't cause the test to fail properly since the goroutine runs concurrently. Consider using a channel orerrgroupto propagate failures.🔎 Proposed fix using errgroup
+import "golang.org/x/sync/errgroup" + factory.Start(stopCh) - go func() { - if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) - } - }() + + var eg errgroup.Group + eg.Go(func() error { + return c.Start(ctx) + }) + defer func() { + if err := eg.Wait(); err != nil && ctx.Err() == nil { + t.Fatalf("Cache failed to start: %v", err) + } + }()client-go/informers/externalversions/device/v1alpha1/gpu.go (1)
89-91: Remove NamespaceIndex from GPU informer—GPU is a cluster-scoped resource.GPU is explicitly marked as
+genclient:nonNamespaced, making it a cluster-scoped resource. ThedefaultInformershould not usecache.NamespaceIndex: cache.MetaNamespaceIndexFuncsince cluster-scoped resources have no namespace semantics.🔎 Proposed fix
Remove the namespace indexer:
func (f *gPUInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredGPUInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) + return NewFilteredGPUInformer(client, resyncPeriod, cache.Indexers{}, f.tweakListOptions) }client-go/examples/fake-server/main.go (1)
185-193:ListMetais not populated in the response.The
GpuListresponse doesn't includemetadata.resource_version, which is needed for clients to establish a watch from a consistent point (List-then-Watch pattern). Consider adding a list-level resource version.🔎 Proposed fix
Track a server-level resource version and populate ListMeta:
+type fakeServer struct { + pb.UnimplementedGpuServiceServer + mu sync.RWMutex + gpus []devicev1alpha1.GPU + listeners map[chan struct{}]chan devicev1alpha1.GPU + resourceVersion int64 // Track global resource version +} func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { s.mu.RLock() defer s.mu.RUnlock() gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: strconv.FormatInt(s.resourceVersion, 10), + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), }
🧹 Nitpick comments (7)
client-go/version/version_test.go (1)
16-18: Consider usingtestify/assertfor assertions.The coding guidelines recommend using
testify/assertortestify/requirefor test assertions.As per coding guidelines, prefer testify assertions:
🔎 Proposed refactor using testify/assert
Add the import:
import ( "fmt" "runtime" "testing" "github.com/stretchr/testify/assert" )Then refactor the assertion:
expected := fmt.Sprintf("nvidia-device-api-client/v1.2.3-test (%s/%s)", runtime.GOOS, runtime.GOARCH) - if got := UserAgent(); got != expected { - t.Errorf("UserAgent() = %q, want %q", got, expected) - } + assert.Equal(t, expected, UserAgent())client-go/DEVELOPMENT.md (2)
10-11: Optional: Adjust list indentation for consistency.Static analysis detected that the nested list items use 4-space indentation instead of the standard 2-space indentation for Markdown.
🔎 Suggested fix
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)
77-77: Optional: Simplify phrase for clarity.The phrase "inside of" can be simplified to "inside" for more concise writing.
🔎 Suggested fix
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.client-go/nvgrpc/options.go (1)
31-36: Godoc comment could be more descriptive.While the function has a comment, it could better explain when and why you'd use this option.
As per coding guidelines.
🔎 Enhanced documentation
-// WithLogger sets the logger to be used by the client. +// WithLogger configures the logger for client operations and interceptors. +// If not provided, the client will use a discard logger. func WithLogger(logger logr.Logger) DialOption {client-go/nvgrpc/config.go (1)
30-31: Default socket path differs from examples.The default socket path is
unix:///var/run/nvidia-device-api/device-api.sock, but examples (e.g.,controller-shim/main.goline 47 andfake-server/main.goline 46) useunix:///tmp/nvidia-device-api.sock. This inconsistency may confuse users.Consider documenting why the paths differ (production vs. dev/test) or standardizing them for consistency across examples.
client-go/client/versioned/typed/device/v1alpha1/device_client.go (1)
53-60: Consider simplifying the error return.
NewForConfigAndClientalways returns anilerror, though the function signature includes an error return. This appears to be for consistency with the parentClientsetpattern (seeclient/versioned/clientset.go). While this provides API uniformity and future-proofing, if no validation or error conditions are anticipated, the signature could be simplified to not return an error.client-go/Makefile (1)
105-113: Verify that excluding examples from build is intentional.The
buildtarget excludesexamples/from compilation (line 108), which means compilation issues in example code won't be detected by CI. While this may be intentional to keep the main build fast, consider adding a separatebuild-examplestarget or including examples in CI to ensure they remain functional as the API evolves.🔎 Optional: Add separate target for examples
.PHONY: build build: code-gen ## Compile all Go code after generation to verify type safety. @echo "Compiling..." go build -v $(LDFLAGS) $$(go list ./... | grep -vE '/hack/overlays/|/examples/') +.PHONY: build-examples +build-examples: code-gen ## Compile example code to verify examples stay current. + @echo "Compiling examples..." + go build -v $(LDFLAGS) ./examples/...
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**api/go.sumis excluded by!**/*.sumclient-go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (71)
.gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/device/v1alpha1/zz_generated.conversion.go(1 hunks)api/device/v1alpha1/zz_generated.deepcopy.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/client/versioned/clientset.go(1 hunks)client-go/client/versioned/fake/clientset_generated.go(1 hunks)client-go/client/versioned/fake/doc.go(1 hunks)client-go/client/versioned/fake/register.go(1 hunks)client-go/client/versioned/integration_test.go(1 hunks)client-go/client/versioned/scheme/doc.go(1 hunks)client-go/client/versioned/scheme/register.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/doc.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/generated_expansion.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/informers/externalversions/device/interface.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/gpu.go(1 hunks)client-go/informers/externalversions/device/v1alpha1/interface.go(1 hunks)client-go/informers/externalversions/factory.go(1 hunks)client-go/informers/externalversions/generic.go(1 hunks)client-go/informers/externalversions/internalinterfaces/factory_interfaces.go(1 hunks)client-go/listers/device/v1alpha1/expansion_generated.go(1 hunks)client-go/listers/device/v1alpha1/gpu.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- api/hack/boilerplate.go.txt
🚧 Files skipped from review as they are similar to previous changes (31)
- client-go/client/versioned/fake/doc.go
- client-go/hack/apply-overlays.sh
- client-go/examples/basic-client/main.go
- client-go/nvgrpc/client_conn_test.go
- client-go/go.mod
- client-go/examples/streaming-daemon/README.md
- .gitignore
- client-go/informers/externalversions/generic.go
- client-go/nvgrpc/client_conn.go
- client-go/examples/controller-shim/README.md
- api/device/v1alpha1/register.go
- client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
- api/device/v1alpha1/doc.go
- api/device/v1alpha1/gpu_conversion_test.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
- client-go/informers/externalversions/device/interface.go
- api/device/v1alpha1/converter.go
- client-go/client/versioned/fake/register.go
- client-go/version/version.go
- api/device/v1alpha1/zz_generated.deepcopy.go
- client-go/client/versioned/typed/device/v1alpha1/generated_expansion.go
- client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
- client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.go
- .versions.yaml
- client-go/examples/basic-client/README.md
- client-go/nvgrpc/watcher_test.go
- client-go/client/versioned/fake/clientset_generated.go
- client-go/nvgrpc/interceptors_test.go
- client-go/informers/externalversions/device/v1alpha1/interface.go
- client-go/nvgrpc/options_test.go
- client-go/informers/externalversions/factory.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/version/version_test.goclient-go/client/versioned/typed/device/v1alpha1/gpu.goclient-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/listers/device/v1alpha1/expansion_generated.goapi/device/v1alpha1/gpu_conversion.goclient-go/client/versioned/typed/device/v1alpha1/fake/doc.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/nvgrpc/options.goclient-go/client/versioned/scheme/register.goclient-go/client/versioned/integration_test.goclient-go/nvgrpc/watcher.goclient-go/client/versioned/clientset.goclient-go/nvgrpc/config.goclient-go/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/interceptors.goclient-go/client/versioned/scheme/doc.goclient-go/examples/fake-server/main.goclient-go/informers/externalversions/device/v1alpha1/gpu.goclient-go/client/versioned/typed/device/v1alpha1/doc.goclient-go/examples/controller-shim/main.goclient-go/listers/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/integration_test.goapi/device/v1alpha1/zz_generated.conversion.goapi/device/v1alpha1/gpu_types.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/version/version_test.goclient-go/nvgrpc/config_test.goclient-go/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/integration_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
api/go.mod
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Extract informer event handler setup into helper methods
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goclient-go/nvgrpc/watcher.goclient-go/informers/externalversions/device/v1alpha1/gpu.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/informers/externalversions/internalinterfaces/factory_interfaces.goapi/go.modclient-go/nvgrpc/watcher.goclient-go/informers/externalversions/device/v1alpha1/gpu.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
api/go.modapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
api/go.mod
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
api/go.modclient-go/client/versioned/scheme/register.goclient-go/nvgrpc/watcher.goclient-go/README.mdclient-go/client/versioned/typed/device/v1alpha1/device_client.goclient-go/client/versioned/scheme/doc.goclient-go/client/versioned/typed/device/v1alpha1/doc.goclient-go/examples/README.mdclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goapi/Makefileclient-go/Makefileclient-go/hack/boilerplate_overlay.go.txtclient-go/DEVELOPMENT.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/client/versioned/typed/device/v1alpha1/doc.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/client/versioned/typed/device/v1alpha1/fake/doc.goclient-go/client/versioned/integration_test.goclient-go/examples/README.mdclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/README.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/client/versioned/integration_test.goclient-go/nvgrpc/watcher.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `testify/assert` and `testify/require` for assertions in Go tests
Applied to files:
client-go/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
client-go/hack/boilerplate.go.txt
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
🧬 Code graph analysis (12)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/client/versioned/typed/device/v1alpha1/device_client.go (5)
DeviceV1alpha1Client(31-34)NewForConfig(43-51)NewForConfigAndClient(55-60)NewForConfigOrDie(64-71)New(74-79)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/informers/externalversions/internalinterfaces/factory_interfaces.go (5)
client-go/client/versioned/clientset.go (1)
Interface(28-30)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/informers/externalversions/device/interface.go (1)
Interface(25-28)client-go/informers/externalversions/device/v1alpha1/interface.go (1)
Interface(24-27)node-drainer/pkg/config/config.go (1)
Duration(37-39)
client-go/nvgrpc/config_test.go (2)
client-go/nvgrpc/config.go (3)
DefaultNvidiaDeviceAPISocket(31-31)NvidiaDeviceAPITargetEnvVar(28-28)Config(41-49)client-go/version/version.go (1)
UserAgent(28-35)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
client-go/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(38-43)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (2)
api/gen/go/device/v1alpha1/gpu_grpc.pb.go (1)
GpuService_WatchGpusClient(100-100)api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
client-go/client/versioned/scheme/register.go (2)
api/device/v1alpha1/register.go (2)
SchemeBuilder(31-31)AddToScheme(34-34)client-go/client/versioned/fake/register.go (1)
AddToScheme(49-49)
client-go/nvgrpc/config.go (1)
client-go/version/version.go (1)
UserAgent(28-35)
client-go/client/versioned/typed/device/v1alpha1/device_client.go (3)
client-go/client/versioned/clientset.go (4)
NewForConfig(48-60)NewForConfigAndClient(64-81)NewForConfigOrDie(85-92)New(95-99)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/examples/fake-server/main.go (5)
commons/pkg/server/server.go (1)
NewServer(375-396)api/gen/go/device/v1alpha1/gpu_grpc.pb.go (1)
RegisterGpuServiceServer(143-152)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/gen/go/device/v1alpha1/gpu.pb.go (9)
ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)Condition(380-398)Condition(411-411)Condition(426-428)Gpu(159-169)Gpu(182-182)Gpu(197-199)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/examples/controller-shim/main.go (7)
client-go/client/versioned/clientset.go (1)
New(95-99)client-go/client/versioned/typed/device/v1alpha1/device_client.go (1)
New(74-79)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/informers/externalversions/factory.go (1)
NewSharedInformerFactory(91-93)client-go/client/versioned/scheme/register.go (1)
Scheme(28-28)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/listers/device/v1alpha1/gpu.go (3)
api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)client-go/listers/device/v1alpha1/expansion_generated.go (1)
GPUListerExpansion(21-21)api/device/v1alpha1/register.go (1)
Resource(25-27)
api/device/v1alpha1/gpu_types.go (1)
api/gen/go/device/v1alpha1/gpu.pb.go (9)
Condition(380-398)Condition(411-411)Condition(426-428)ObjectMeta(40-53)ObjectMeta(66-66)ObjectMeta(81-83)ListMeta(100-112)ListMeta(125-125)ListMeta(140-142)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (57)
client-go/hack/boilerplate.go.txt (1)
1-13: License header is complete and compliant.The Apache 2.0 license header is properly formatted with the copyright notice, license URL, and all required disclaimers. This boilerplate template will be used by code generation tools to prepend headers to generated files.
client-go/hack/boilerplate_overlay.go.txt (1)
1-15: License header and generated code notice are properly formatted.The Apache 2.0 license header matches the standard boilerplate, and the "Code generated by client-gen and gRPC overlay. DO NOT EDIT." notice (line 15) appropriately warns against manual edits of overlay-applied files. This template will be used by the overlay application workflow to mark generated files as auto-generated.
client-go/examples/README.md (1)
1-38: Documentation is clear and well-organized.The README effectively communicates the purpose of each example, provides straightforward prerequisites and setup instructions, and accurately describes the directory structure. The table links (lines 9–11) now use correct relative paths (
./basic-client,./streaming-daemon,./controller-shim) that will resolve properly from the examples/ directory context—this incorporates the feedback from the previous review comment successfully.The instruction on line 30 appropriately assumes execution from the repository root, which is a common pattern and poses no confusion when combined with the relative table links that serve browser/editor navigation.
client-go/client/versioned/typed/device/v1alpha1/fake/doc.go (1)
1-18: Generated fake client looks correct; prefer envtest for controller tests.The generated doc.go file follows standard client-go patterns with proper license header, generation notice, and package documentation. However, when writing actual test code for Kubernetes controllers, prefer
envtestover fake clients for more realistic integration testing.Based on learnings, envtest provides better coverage by running against a real API server rather than in-memory fakes.
client-go/version/version_test.go (2)
10-11: Good cleanup pattern.The defer ensures
GitVersionis restored even if the test fails or panics.
9-19: The test correctly saves and restores the package-levelGitVersionvariable using defer. Since tests within a package run sequentially by default and this test does not callt.Parallel(), there is no risk of concurrent access or race conditions.Likely an incorrect or invalid review comment.
client-go/client/versioned/typed/device/v1alpha1/doc.go (1)
1-18: LGTM: Generated code follows standard conventions.The file correctly includes the Apache 2.0 license header, generation notice, and package-level documentation as required by coding guidelines.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
17-24: LGTM: ClientConn implementation is appropriate for fake client.The method correctly returns a nil
*grpc.ClientConncast to the interface, which is appropriate for a fake implementation that uses an in-memory ObjectTracker instead of actual gRPC connections. The documentation clearly explains this behavior.api/go.mod (3)
3-3: Go toolchain update looks good.The update from go 1.25.0 to go 1.25.5 is a patch-level toolchain update that should include bug fixes and improvements.
6-6: Dependency version is current.The addition of
github.com/google/go-cmp v0.7.0is appropriate. This is the latest stable version and suitable for testing and comparison utilities in the codebase.
16-34: k8s.io/apimachinery v0.34.1 is stable and compatible.No known vulnerabilities exist for this version. It is current (published August 2025), part of the active Kubernetes 1.34 support window, and the related ecosystem dependencies are properly aligned. The version safely integrates with client-go SDK as intended.
client-go/DEVELOPMENT.md (1)
1-105: LGTM: Comprehensive development documentation.The DEVELOPMENT.md provides clear, well-structured guidance covering prerequisites, workflow, code generation pipeline, overlay patterns, directory structure, and housekeeping. The content accurately reflects the PR's multi-stage code generation approach.
client-go/listers/device/v1alpha1/gpu.go (1)
1-46: LGTM: Generated lister follows Kubernetes conventions.The GPULister implementation correctly follows client-go patterns with a typed interface, read-only semantics clearly documented, and proper initialization using the ResourceIndexer pattern. The code generation marker and license header are present.
client-go/listers/device/v1alpha1/expansion_generated.go (1)
1-21: LGTM: Standard expansion interface pattern.The empty GPUListerExpansion interface follows the standard Kubernetes pattern for allowing custom methods to be added to generated listers without modifying generated code. The file is properly marked as generated with appropriate license headers.
client-go/nvgrpc/options.go (1)
38-50: LGTM: Interceptor options follow functional pattern.The
WithUnaryInterceptorandWithStreamInterceptorfunctions correctly append interceptors to their respective chains, allowing multiple interceptors to be composed together. The implementation properly follows the functional options pattern.api/device/v1alpha1/gpu_types.go (4)
21-30: LGTM: GPUSpec is well-documented.The GPUSpec type clearly documents the UUID field with its expected format and example. The deepcopy generation annotation is correctly placed.
32-45: LGTM: GPUStatus follows Kubernetes conventions.The GPUStatus correctly uses
metav1.Conditionfor the Conditions field, following standard Kubernetes API patterns. The RecommendedAction field is well-documented with appropriate optional markers.
47-61: LGTM: GPU resource annotations are appropriate.The
genclientannotations correctly specify this as a non-namespaced, read-only resource (get/list/watch only) with no status subresource. The struct composition with TypeMeta and ObjectMeta follows standard Kubernetes resource patterns.
63-71: LGTM: GPUList follows standard list patterns.The GPUList type correctly includes TypeMeta, ListMeta, and an Items slice, following the standard Kubernetes list resource pattern. The deepcopy and runtime.Object annotations are properly configured.
api/proto/device/v1alpha1/gpu.proto (4)
53-70: LGTM! Gpu message follows Kubernetes resource model.The refactoring to use ObjectMeta and the addition of GpuStatus correctly implements the Kubernetes Spec/Status pattern. The comments provide clear guidance on resource naming conventions.
72-78: GpuList structure updated consistently.The addition of ListMeta and repositioning of items field aligns with the ObjectMeta/ListMeta pattern. Note that changing field positions is a protobuf breaking change, which is acknowledged in the PR objectives.
80-117: Status types are well-structured and documented.GpuSpec, GpuStatus, and Condition messages follow Kubernetes API conventions with comprehensive field documentation. The Condition type correctly implements the standard Kubernetes condition pattern.
Based on learnings, comprehensive comments for all fields are present as required.
119-185: Service definition and request/response messages are complete.The GpuService RPCs (Get, List, Watch) provide appropriate operations for GPU resource management. The addition of resource_version fields to ListGpusRequest and WatchGpusRequest enables versioned operations and watch semantics as intended. Event types in WatchGpusResponse are clearly documented.
client-go/client/versioned/typed/device/v1alpha1/gpu.go (4)
31-49: Interface design follows client-go conventions.The GPUsGetter and GPUInterface definitions correctly follow Kubernetes client-go patterns. The GPUExpansion interface allows for future extensibility without breaking changes.
As per coding guidelines, using client-go patterns for Kubernetes API interactions is the recommended approach.
51-57: Constructor correctly initializes the GPU client.The newGPUs constructor properly wires the gRPC client and scopes the logger with WithName("gpus"), which aids in debugging and observability.
59-87: Get and List methods are correctly implemented.Both methods properly handle gRPC calls, perform protobuf-to-internal conversions, and log operations at appropriate verbosity levels. Errors are returned directly without wrapping, which is correct for gRPC calls to preserve status codes.
89-103: Watch method correctly manages streaming and context lifecycle.The Watch implementation properly creates a cancellable context, handles error cleanup by calling cancel before returning, and passes the cancel function to nvgrpc.NewWatcher for proper stream closure. This prevents resource leaks.
As per coding guidelines, this implements proper shutdown handling with context cancellation.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (5)
9-22: Client interface and struct follow client-go patterns.The DeviceV1alpha1Interface correctly embeds GPUsGetter and exposes ClientConn for transport access. The GPUs() method properly delegates to the newGPUs constructor for resource client instantiation.
24-35: NewForConfig correctly handles connection setup.The shallow copy of the config prevents mutation, and error handling for connection establishment is appropriate. The delegation to NewForConfigAndClient avoids code duplication.
37-44: NewForConfigAndClient properly initializes the client with provided connection.The method correctly prioritizes the provided connection over config transport values and scopes the logger appropriately. The error return enables consistent API patterns across constructors.
46-63: OrDie and minimal constructors follow client-go conventions.NewForConfigOrDie correctly panics on error (expected for "OrDie" pattern), and New provides a minimal constructor with a discarded logger for simple use cases. Both patterns align with Kubernetes client-go practices.
65-73: ClientConn accessor includes appropriate nil safety.The nil check on the receiver prevents potential panics and follows defensive programming practices.
api/device/v1alpha1/zz_generated.conversion.go (6)
11-22: FromProtobuf method implements proper nil safety.The conversion from protobuf Gpu to internal GPU type correctly checks for nil source and delegates to field-specific converters. The structure follows generated code best practices.
23-33: Condition conversion correctly maps all fields.The FromProtobufCondition method properly converts all condition fields including the Status cast to v1.ConditionStatus and uses the FromProtobufTimestamp helper for timestamp conversion.
34-49: List conversion handles nil safety and slice allocation correctly.The FromProtobufList method properly checks for nil source and Items, allocates the slice with the correct length, and converts each element. The pattern is appropriate for generated conversion code.
50-64: Metadata converters implement required subset of k8s metadata.FromProtobufListMeta and FromProtobufObjectMeta correctly map the essential fields (Name, ResourceVersion) with appropriate nil checks. This aligns with the proto definition of ObjectMeta and ListMeta as subsets of Kubernetes metadata types.
65-84: Spec and Status converters handle field mappings correctly.FromProtobufSpec correctly maps the UUID field with appropriate case conversion (Uuid -> UUID). FromProtobufStatus handles the Conditions slice with proper nil checking and element-by-element conversion.
85-142: ToProtobuf methods correctly reverse the conversion direction.All ToProtobuf methods properly convert from internal types to protobuf types with appropriate nil safety where needed. The conversions mirror the FromProtobuf logic correctly, including the Status to string cast and slice handling.
client-go/examples/fake-server/README.md (1)
1-18: README provides clear documentation for the fake server.The README effectively documents the fake server's purpose, usage, and behavior. The instructions are concise and the simulation behavior (8 GPUs with 2-second status toggling) is well-explained for testing Watch streams and controllers.
client-go/client/versioned/scheme/doc.go (1)
1-18: Package documentation follows Go conventions.The doc.go file correctly provides package-level documentation as required by coding guidelines. The license header and generated code notice are appropriate.
As per coding guidelines, package-level godoc is required for all Go packages.
client-go/nvgrpc/config_test.go (3)
20-59: Target precedence test correctly validates configuration defaults.The table-driven test structure follows Go testing best practices and comprehensively covers the precedence order (explicit > env var > default). The use of t.Setenv ensures proper cleanup between subtests.
As per coding guidelines, this test uses the table-driven format when testing multiple scenarios.
61-80: UserAgent default test validates expected behavior.The test correctly verifies that Default() populates an empty UserAgent and preserves custom values. The subtest structure improves clarity and isolation.
82-120: Validation test comprehensively covers required field checks.The table-driven test correctly validates that Config.Validate() enforces required fields (Target, UserAgent) and allows valid configurations. The error checking pattern is idiomatic.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (2)
9-23: Next method correctly handles stream events and conversions.The Next() method properly receives stream events, handles errors immediately, and converts protobuf objects to runtime.Object using FromProto. The use of GetType() and GetObject() accessor methods is safe.
25-27: Close method correctly closes the gRPC stream.The Close() method properly calls CloseSend() on the underlying stream and propagates any errors, ensuring proper resource cleanup.
client-go/nvgrpc/watcher.go (1)
38-76: LGTM: Stop() is now properly idempotent.The
sync.Oncefield (line 44) and its usage inStop()(line 68-75) correctly ensures that shutdown happens exactly once, addressing the previous race condition concern. This makesStop()safe for concurrent calls, including thedefer w.Stop()inreceive().client-go/client/versioned/typed/device/v1alpha1/device_client.go (5)
25-28: LGTM!The interface design is clean and follows good Go practices by exposing the underlying connection via
ClientConn()and embedding resource-specific getters.
30-34: LGTM!The struct design appropriately encapsulates the gRPC connection and logger, following structured logging practices as specified in the coding guidelines.
36-38: LGTM!The method correctly delegates to
newGPUs(), which is implemented via the overlay pattern mentioned in the PR objectives.
62-79: LGTM!Both constructors follow standard Kubernetes client-go patterns:
NewForConfigOrDiefor CLI tools that should fail fast, andNewwith a discard logger for cases where configuration is unavailable.
81-89: LGTM!The
ClientConn()method includes appropriate nil-safety checks and provides access to the underlying gRPC connection when needed.client-go/Makefile (6)
19-83: LGTM!The configuration section is well-structured with clear variable naming, appropriate fallbacks (e.g., GO_VERSION detection), and helpful error messaging for missing prerequisites (yq). The use of a centralized
.versions.yamlfile for tool versioning is a good practice for maintainability.
89-96: LGTM!The
alltarget follows a logical order (code-gen → test → build), and the help formatter uses the standard awk pattern for extracting target documentation.
100-103: LGTM!The target dependencies are correctly ordered: generating the client, applying overlays, then generating listers/informers that depend on the overlaid client code. The final
go mod tidyensures module consistency.
115-144: LGTM!The code generator targets are correctly configured with appropriate flags, dependencies on their respective tools, and clean targets to remove stale generated code. The flags follow standard Kubernetes code-generator conventions.
146-176: LGTM!The overlay and cleanup targets provide appropriate granularity for managing generated code and tools. The hierarchical clean targets (
clean,purge,clean-*) offer good flexibility for different cleanup scenarios.
198-213: LGTM!The
go-install-toolmacro is well-designed: it avoids reinstalling identical versions via version suffixes, uses symlinks for convenient access, and correctly setsGOTOOLCHAINto ensure the right Go version is used for tool compilation.
1776d86 to
1072d57
Compare
There was a problem hiding this 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
♻️ Duplicate comments (6)
.versions.yaml (1)
49-50: Update goverter version - v1.9.2 does not exist.The goverter version v1.9.2 specified does not exist. The latest released version is v1.8.2. Update to use an actual released version.
Run the following script to verify the latest goverter release:
#!/bin/bash # Check the latest release of goverter gh api repos/jmattheis/goverter/releases/latest --jq '.tag_name'client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-1: Add package-level godoc comment.The package lacks documentation. As per coding guidelines, package-level godoc is required for all Go packages.
As per coding guidelines.
13-15: Add function comment for exported method.The
GPUs()method is missing documentation. As per coding guidelines, function comments are required for all exported Go functions.As per coding guidelines.
client-go/hack/overlays/client/versioned/integration_test.go (1)
210-214: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorffrom a goroutine is unsafe and can cause race conditions. The cache'sStartmethod runs until context cancellation, so errors should be captured via a channel.api/proto/device/v1alpha1/gpu.proto (1)
35-37: Fix inconsistent indentation in comment blocks.Some comment lines use tabs while surrounding lines use spaces, creating inconsistent formatting.
Also applies to: 47-48
client-go/Makefile (1)
187-187: Declare thetoolstarget as PHONY.The
toolstarget should be declared.PHONYsince it doesn't produce a file output and serves as a convenience alias for tool binaries.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)
🧹 Nitpick comments (9)
client-go/version/version_test.go (3)
9-9: Refactor test name to follow the coding guideline convention.The test name should follow the format
TestFunctionName_Scenario_ExpectedBehavior. Consider renaming to something likeTestUserAgent_WithCustomVersion_ReturnsFormattedString.As per coding guidelines for
**/*_test.go: "Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior"
16-18: Use testify for assertions per coding guidelines.The test uses plain
t.Errorffor assertions, but the coding guidelines specify usingtestify/assertortestify/require.🔎 Proposed refactor using testify/assert
import ( - "fmt" "runtime" "testing" + + "github.com/stretchr/testify/assert" ) func TestUserAgent(t *testing.T) { originalVersion := GitVersion defer func() { GitVersion = originalVersion }() GitVersion = "v1.2.3-test" - expected := fmt.Sprintf("nvidia-device-api-client/v1.2.3-test (%s/%s)", runtime.GOOS, runtime.GOARCH) - if got := UserAgent(); got != expected { - t.Errorf("UserAgent() = %q, want %q", got, expected) - } + expected := "nvidia-device-api-client/v1.2.3-test (" + runtime.GOOS + "/" + runtime.GOARCH + ")" + assert.Equal(t, expected, UserAgent()) }As per coding guidelines for
**/*_test.go: "Usetestify/assertandtestify/requirefor assertions in Go tests"
9-19: Consider table-driven tests for multiple scenarios.While the current test correctly verifies the UserAgent function, consider using a table-driven approach to test multiple scenarios (e.g., default "devel" version, various version formats, edge cases).
🔎 Example table-driven refactor
func TestUserAgent(t *testing.T) { + tests := []struct { + name string + gitVersion string + }{ + {"custom version", "v1.2.3-test"}, + {"devel version", "devel"}, + {"empty version", ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + originalVersion := GitVersion + defer func() { GitVersion = originalVersion }() + + GitVersion = tt.gitVersion + + expected := "nvidia-device-api-client/" + tt.gitVersion + " (" + runtime.GOOS + "/" + runtime.GOARCH + ")" + assert.Equal(t, expected, UserAgent()) + }) + } - originalVersion := GitVersion - defer func() { GitVersion = originalVersion }() - - GitVersion = "v1.2.3-test" - - expected := fmt.Sprintf("nvidia-device-api-client/v1.2.3-test (%s/%s)", runtime.GOOS, runtime.GOARCH) - if got := UserAgent(); got != expected { - t.Errorf("UserAgent() = %q, want %q", got, expected) - } }As per coding guidelines for
**/*_test.go: "Write table-driven tests when testing multiple scenarios in Go"Note: The core test logic (state save/restore, version override, format verification) is correct and properly implemented.
client-go/DEVELOPMENT.md (2)
10-11: Optional: Fix markdown list indentation.The nested list items use 4 spaces instead of the standard 2 spaces for indentation, which markdownlint flags.
🔎 Suggested fix
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)
77-77: Optional: Simplify phrasing."inside of" can be simplified to "inside" for more concise documentation.
🔎 Suggested fix
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.client-go/nvgrpc/config.go (1)
40-49: Add a public method to configure the logger.The
loggerfield is unexported and there's no public setter method, which prevents users from configuring custom logging. Users must rely onDefault()setting a discard logger, limiting observability.🔎 Proposed addition of WithLogger method
Add a method to allow users to configure a logger:
+// WithLogger sets the logger for the Config. +func (c *Config) WithLogger(logger logr.Logger) *Config { + c.logger = logger + return c +}This enables fluent configuration like:
config := &nvgrpc.Config{Target: "unix://..."} config.WithLogger(myLogger).Default()client-go/nvgrpc/watcher_test.go (1)
31-58: Consider using testify for more expressive assertions.The tests use basic Go assertions (
t.Fatalf,t.Errorf), which work but are less expressive than testify assertions. The coding guidelines recommend usingtestify/assertandtestify/requirefor clearer test failures.As per coding guidelines for
**/*_test.go: "Usetestify/assertandtestify/requirefor assertions in Go tests"Example refactor using testify
+import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) func TestWatcher_NormalEvents(t *testing.T) { // ... setup ... wantTypes := []watch.EventType{watch.Added, watch.Modified, watch.Deleted} - if len(got) != len(wantTypes) { - t.Fatalf("got %d events, want %d", len(got), len(wantTypes)) - } + require.Len(t, got, len(wantTypes), "unexpected number of events") + for i, ev := range got { - if ev.Type != wantTypes[i] { - t.Errorf("event %d: got type %v, want %v", i, ev.Type, wantTypes[i]) - } + assert.Equal(t, wantTypes[i], ev.Type, "event %d type mismatch", i) } }Also applies to: 60-83, 85-118, 120-152, 154-177
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
57-63: Consider accepting an optional logger parameter in New().The
New()constructor always uses a discard logger with no way to configure logging afterwards. For production observability, consider adding a variadic options parameter or a separateNewWithLogger()constructor.🔎 Proposed enhancement using functional options
+type ClientOption func(*DeviceV1alpha1Client) + +func WithLogger(logger logr.Logger) ClientOption { + return func(c *DeviceV1alpha1Client) { + c.logger = logger + } +} + // New creates a new DeviceV1alpha1Client for the given gRPC client connection. -func New(c grpc.ClientConnInterface) *DeviceV1alpha1Client { - return &DeviceV1alpha1Client{ +func New(c grpc.ClientConnInterface, opts ...ClientOption) *DeviceV1alpha1Client { + client := &DeviceV1alpha1Client{ conn: c, logger: logr.Discard(), } + for _, opt := range opts { + opt(client) + } + return client }client-go/Makefile (1)
198-213: Simplify redundant error suppression in go-install-tool.Line 208 uses
rm -f $(1) || true, but the-fflag already suppresses errors, making|| trueredundant.🔎 Proposed simplification
echo "Downloading $${package}" ;\ -rm -f $(1) || true ;\ +rm -f $(1) ;\ GOBIN=$(LOCALBIN) GOTOOLCHAIN=$(GO_VERSION) go install $${package} ;\
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (47)
.coderabbit.yaml(1 hunks).gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (5)
- client-go/hack/boilerplate_overlay.go.txt
- client-go/README.md
- client-go/nvgrpc/config_test.go
- client-go/examples/streaming-daemon/README.md
- client-go/hack/boilerplate.go.txt
🚧 Files skipped from review as they are similar to previous changes (20)
- api/device/v1alpha1/gpu_conversion_test.go
- client-go/examples/README.md
- client-go/version/version.go
- client-go/nvgrpc/client_conn.go
- client-go/nvgrpc/client_conn_test.go
- client-go/examples/controller-shim/README.md
- client-go/go.mod
- client-go/examples/basic-client/main.go
- client-go/nvgrpc/options.go
- client-go/examples/fake-server/README.md
- api/device/v1alpha1/register.go
- client-go/examples/fake-server/main.go
- client-go/nvgrpc/interceptors_test.go
- client-go/nvgrpc/options_test.go
- client-go/examples/controller-shim/main.go
- .gitignore
- api/hack/boilerplate.go.txt
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
- api/device/v1alpha1/converter.go
- client-go/examples/basic-client/README.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/nvgrpc/interceptors.goapi/device/v1alpha1/gpu_types.goclient-go/nvgrpc/config.goclient-go/version/version_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goapi/device/v1alpha1/doc.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/watcher_test.goapi/device/v1alpha1/gpu_conversion.goclient-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
api/go.mod
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/version/version_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.go
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
.versions.yamlapi/go.modapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
.versions.yamlclient-go/hack/apply-overlays.shapi/go.modclient-go/nvgrpc/config.goclient-go/DEVELOPMENT.mdclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
.versions.yamlclient-go/version/version_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
api/go.mod
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
api/go.modclient-go/nvgrpc/watcher.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
client-go/version/version_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
🧬 Code graph analysis (9)
client-go/nvgrpc/config.go (1)
client-go/version/version.go (1)
UserAgent(28-35)
client-go/version/version_test.go (1)
client-go/version/version.go (2)
GitVersion(25-25)UserAgent(28-35)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/hack/overlays/client/versioned/integration_test.go (5)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
NewForConfigAndClient(39-44)New(58-63)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
api/device/v1alpha1/gpu_conversion.go (2)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/examples/streaming-daemon/main.go (5)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(58-63)NewForConfigAndClient(39-44)client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (6)
DeviceV1alpha1Interface(9-12)DeviceV1alpha1Client(15-18)NewForConfig(27-35)NewForConfigAndClient(39-44)NewForConfigOrDie(48-55)New(58-63)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (40)
api/go.mod (2)
3-3: LGTM! Go toolchain update is appropriate.The Go toolchain update from 1.25.0 to 1.25.5 is a patch-level update that's appropriate for this PR.
6-6: LGTM! Dependencies align with client-go SDK objectives.The new dependencies (go-cmp, k8s.io/apimachinery, and related transitive dependencies) are appropriate for the Kubernetes client-go SDK integration and API generation work described in the PR objectives.
Also applies to: 16-33
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (3)
10-12: LGTM! Clean adapter abstraction.The gpuStreamAdapter provides a clean abstraction over the gRPC stream, wrapping it to provide Kubernetes-compatible event semantics.
14-23: LGTM! Proper error handling and conversion logic.The Next() method correctly:
- Handles gRPC Recv() errors with early return
- Converts protobuf messages to runtime.Object via FromProto
- Returns the event type and converted object
25-27: LGTM! Appropriate stream cleanup.The Close() method correctly calls CloseSend() to properly close the client-side gRPC stream.
api/device/v1alpha1/gpu_conversion.go (3)
15-15: LGTM! Appropriate build tag.The
!goverterbuild tag correctly excludes this file when goverter generates conversion code, preventing conflicts.
21-32: LGTM! Clean singleton pattern with proper nil handling.The converter singleton and FromProto helper correctly:
- Initialize the singleton converter instance
- Check for nil input and return nil
- Delegate to the generated converter and handle pointer conversions properly
34-56: LGTM! Consistent conversion helpers.All conversion helpers (ToProto, FromProtoList, ToProtoList) follow the same pattern with:
- Proper nil checks
- Correct pointer handling
- Delegation to the converter implementation
api/Makefile (6)
19-37: LGTM! Well-structured version and package scaffolding.The string manipulation helpers, API version variables, and package path helpers provide clean, maintainable support for per-version code generation workflows.
55-79: LGTM! Clean tool management and version centralization.The GO_VERSION detection, tool binary definitions, and centralized version loading from .versions.yaml provide good maintainability and consistency across the build system.
86-99: LGTM! Comprehensive code generation workflow.The updated
alltarget and newcode-gentarget properly orchestrate the multi-stage generation pipeline (tools → protos → deepcopy → conversion → tidy), aligning with the PR's objectives for generated client-go SDK.
111-141: LGTM! Per-version generation targets are well-structured.The proto, deepcopy, and conversion generation targets correctly:
- Loop over API_VERSIONS for per-version processing
- Use appropriate tool flags and options
- Include clean targets for each generation type
143-167: LGTM! Comprehensive cleanup targets.The clean, purge, and per-artifact clean targets provide thorough cleanup capabilities for all generated artifacts.
194-205: LGTM! Proper toolchain propagation.The go-install-tool macro correctly propagates GOTOOLCHAIN=$(GO_VERSION) during tool installation, ensuring tools are built with the correct Go version.
api/device/v1alpha1/doc.go (1)
15-19: LGTM! Proper Kubernetes API group documentation.The package documentation correctly includes:
- Kubebuilder group marker (+groupName=device.nvidia.com)
- Clear description of package contents (GPU resources, conversions)
- Standard Go package doc format
.coderabbit.yaml (1)
19-24: LGTM! Appropriate exclusion of generated code.The path_filters correctly exclude generated/boilerplate code paths (protobuf bindings, zz_generated.* files, generated clientset/listers/informers), which aligns with the PR's objective to add generated client-go SDK components.
client-go/hack/apply-overlays.sh (3)
5-5: LGTM! Strict error handling enabled.The script correctly uses
set -euo pipefailfor strict error handling (exit on error, undefined variables, and pipeline failures).
7-20: LGTM! Proper validation checks.The script includes appropriate validation:
- Verifies boilerplate file exists
- Ensures execution from repository root (checks go.mod)
- Exits with clear error messages on validation failures
22-29: LGTM! Clean overlay application logic.The find loop correctly:
- Processes all .go files in the overlay directory
- Strips the overlay prefix to compute destination paths
- Creates destination directories as needed
- Concatenates boilerplate with overlay source
- Provides clear progress output
client-go/examples/streaming-daemon/main.go (3)
49-52: LGTM: Clean interceptor implementation.The inline unary interceptor properly injects tracing metadata and delegates to the invoker. The implementation is straightforward and correct.
88-94: LGTM: Proper error handling for List operation.The List operation correctly uses the timeout context and handles errors appropriately, logging the GPU count on success.
96-143: LGTM: Well-structured watch loop with proper cleanup.The watch implementation demonstrates several best practices:
- Deferred watcher cleanup with
Stop()- Proper channel close detection
- Watch error handling with status extraction
- Type assertion safety check
- Context cancellation handling
The event processing logic correctly extracts GPU readiness status from conditions.
client-go/nvgrpc/interceptors.go (2)
27-59: LGTM: Proper unary interceptor implementation.The latency interceptor correctly:
- Measures RPC duration without disrupting the call flow
- Uses appropriate log levels for different scenarios (V(4) for context errors, Error() for failures, V(6) for success)
- Preserves the original error for proper error propagation
- Includes relevant metadata (method, duration, status code)
61-92: LGTM: Proper stream interceptor implementation.The stream interceptor follows the same solid pattern as the unary interceptor. The success logging at V(4) (vs V(6) for unary) appears intentional, likely because stream establishment is more significant than individual unary calls.
client-go/hack/overlays/client/versioned/integration_test.go (4)
64-72: LGTM: Straightforward Get test.The test properly validates the Get operation, checking both successful retrieval and the resource name.
88-129: LGTM: Comprehensive Watch flow test.The test validates both the initial snapshot (ADDED events) and subsequent live updates (MODIFIED events), with proper timeout handling and type safety checks.
137-139: LGTM: Correct informer initialization order.The code properly instantiates the informer before starting the factory, which is required to register it with the factory.
299-333: LGTM: Well-structured mock WatchGpus implementation.The mock properly:
- Sends initial snapshot under read lock
- Handles context cancellation during snapshot
- Streams live events from the watch channel
- Returns on channel close or context cancellation
api/proto/device/v1alpha1/gpu.proto (2)
27-51: LGTM: Well-designed metadata messages.The
ObjectMetaandListMetamessages properly mirror Kubernetes API conventions, enabling resource versioning, optimistic concurrency, and watch semantics. The comments appropriately reference the Kubernetes API conventions documentation.
152-167: LGTM: Resource version support for watch resumption.Adding
resource_versionfields toListGpusRequestandWatchGpusRequestenables clients to resume watches from a specific point and perform consistent list operations, aligning with Kubernetes watch semantics.client-go/hack/overlays/client/versioned/clientset.go (3)
26-44: LGTM: Well-documented constructor with defensive copying.The
NewForConfigconstructor properly validates input, creates the gRPC connection, and delegates toNewForConfigAndClient. The shallow copy at line 37 protects against config mutation. The documentation clearly explains when to use this vs. manually creating a connection.
46-65: LGTM: Robust validation and defensive copying.The constructor properly validates both parameters and performs defensive copying before passing the config to the device client constructor. The nil checks provide clear error messages.
67-76: LGTM: Appropriate panic behavior for OrDie pattern.The
NewForConfigOrDiefunction follows the Kubernetes convention for "OrDie" constructors, panicking on configuration errors. This is appropriate for initialization code where recovery is not possible.api/device/v1alpha1/gpu_types.go (4)
21-30: LGTM: Clean spec definition with clear documentation.The
GPUSpecproperly defines the GPU identity with clear field documentation and format examples.
32-45: LGTM: Status definition follows Kubernetes conventions.The
GPUStatuscorrectly usesmetav1.Conditionfor status conditions, aligning with Kubernetes best practices. Both fields are appropriately marked as optional.As per coding guidelines.
47-61: LGTM: Appropriate genclient markers for read-only cluster resource.The markers correctly configure this as:
- A cluster-scoped resource (
nonNamespaced)- Read-only verbs only (
onlyVerbs=get,list,watch)- No separate status subresource (
noStatus)This configuration is appropriate for a hardware resource that's observed but not mutated through the API.
63-71: LGTM: Proper list type with required markers.The
GPUListincludes the necessary deepcopy and runtime.Object markers, and properly embedsListMetafor list pagination and versioning support.client-go/nvgrpc/watcher.go (2)
48-63: LGTM! Well-structured watcher initialization.The watcher is properly initialized with buffered channels, context cancellation support, and scoped logging. The race condition identified in previous reviews has been correctly addressed using
sync.Once.
138-170: LGTM! Comprehensive error mapping for Informer integration.The error translation logic correctly maps gRPC status codes to Kubernetes status reasons, with special handling for codes that should trigger Informer relist operations (410 Expired). The comment on line 148 clearly explains the critical behavior.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
65-73: LGTM! Defensive nil-check prevents panics.The nil-check on the receiver (line 68) is good defensive programming that prevents potential nil pointer dereferences when accessing the connection.
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
api/go.mod (1)
1-34: Fix module version format to resolve pipeline failure.The pipeline reports a critical error:
gomod-lintexpects local modules to usev0.0.0(without timestamp), but the current version isv0.0.0-00010101000000-000000000000.This is blocking the build pipeline. Ensure the
replacedirective or module version follows the expected format for local modules.#!/bin/bash # Verify the go.mod format and any replace directives cat api/go.mod | grep -E "(module|replace)" -A1
♻️ Duplicate comments (10)
client-go/version/version.go (1)
15-15: Add package-level godoc comment.The coding guidelines require package-level godoc for all Go packages. A package comment describing the purpose of this package is still missing.
As per coding guidelines, package-level godoc is required for all Go packages.
client-go/nvgrpc/client_conn_test.go (1)
23-57: Use testify for assertions as required by coding guidelines.The tests use stdlib
t.Fatalf/t.Errorinstead oftestify/requireandtestify/assert. This was flagged in a previous review and should be addressed.🔎 Example refactor using testify
import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/go-logr/logr" ) func TestClientConnFor(t *testing.T) { t.Run("Config defaulting does not mutate original", func(t *testing.T) { cfg := &Config{} conn, err := ClientConnFor(cfg) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } + require.NoError(t, err) + require.NotNil(t, conn) defer conn.Close() - if cfg.Target != "" { - t.Errorf("Original config was mutated! Target is %q", cfg.Target) - } + assert.Empty(t, cfg.Target, "Original config should not be mutated") }) t.Run("Config.Default() works correctly", func(t *testing.T) { cfg := &Config{} cfg.Default() - if cfg.Target == "" { - t.Error("Target was not defaulted") - } - if cfg.UserAgent == "" { - t.Error("UserAgent was not defaulted") - } + assert.NotEmpty(t, cfg.Target, "Target should be defaulted") + assert.NotEmpty(t, cfg.UserAgent, "UserAgent should be defaulted") }) t.Run("Client creation respects WithLogger option", func(t *testing.T) { cfg := &Config{Target: "unix:///tmp/test.sock"} conn, err := ClientConnFor(cfg, WithLogger(logr.Discard())) - if err != nil { - t.Fatalf("failed to create client: %v", err) - } + require.NoError(t, err) + require.NotNil(t, conn) conn.Close() }) }Based on coding guidelines.
client-go/examples/fake-server/main.go (1)
181-194: Populate ListMeta.ResourceVersion for List-then-Watch semantics.The
GpuListresponse doesn't includeMetadata.ResourceVersion, which clients need to establish a consistent Watch point. This was flagged in a previous review.🔎 Suggested fix
+func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + // Determine the highest resource version across all GPUs + maxRV := "0" + for _, gpu := range s.gpus { + if gpu.ResourceVersion > maxRV { + maxRV = gpu.ResourceVersion + } + } + gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: maxRV, + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), } for _, gpu := range s.gpus { gpuList.Items = append(gpuList.Items, devicev1alpha1.ToProto(&gpu)) } return &pb.ListGpusResponse{GpuList: gpuList}, nil }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
37-44: Validate the config in NewForConfigAndClient.The past review comment correctly identified that
NewForConfigAndClientdoesn't validate the config before using it. While the config is primarily used for logger extraction, adding validation would ensure consistency with theNewForConfigpath.api/proto/device/v1alpha1/gpu.proto (1)
27-51: Fix inconsistent indentation in comment blocks.Lines 35-37 use tabs while surrounding lines use spaces, creating inconsistent formatting. This was flagged in a previous review.
🔎 Suggested fix
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-11: Add package-level godoc comment.The coding guidelines require package-level documentation for all Go packages. This was previously flagged and appears unaddressed.
As per coding guidelines.
🔎 Suggested documentation
+// Package fake provides fake implementations of the device v1alpha1 client +// for testing purposes. These fakes use an in-memory ObjectTracker instead +// of actual gRPC connections. package fake
13-15: Add function comment for exported method.The coding guidelines require function comments for all exported Go functions. This was previously flagged.
As per coding guidelines.
🔎 Suggested documentation
+// GPUs returns a fake GPUInterface for testing GPU operations +// without requiring an actual gRPC connection. func (c *FakeDeviceV1alpha1) GPUs() v1alpha1.GPUInterface { return newFakeGPUs(c) }client-go/examples/controller-shim/main.go (1)
58-62: The informer factory is never started.The comment on line 60 states the Manager will start the injected informer, but controller-runtime only starts informers created through its own cache machinery. The gRPC-backed informer from
factoryneeds to be started explicitly; otherwise, the cache will never populate and reconciliation won't occur.🔎 Suggested fix
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + // Start the factory in a background goroutine before the manager starts. + stopCh := make(chan struct{}) + go factory.Start(stopCh) + // Initialize the controller-runtime Manager.Then ensure
stopChis closed on shutdown (e.g., viadefer close(stopCh)after manager setup, or tie it to the signal handler context).client-go/hack/overlays/client/versioned/integration_test.go (1)
210-214: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorf(or anytmethod) from a goroutine is unsafe and can cause race conditions or panics if the test completes before the goroutine executes.🔎 Suggested fix using an error channel
+ errCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + errCh <- err } + close(errCh) }()Alternatively, since
c.Startblocks until context cancellation and typically only returns errors on shutdown, you could log the error or uset.Logfor informational purposes, as the cache sync check will catch initialization failures.client-go/Makefile (1)
187-187: Declaretoolstarget as.PHONY.The
toolstarget should be declared.PHONYsince it doesn't produce a file and is used as a convenience alias for tool binaries.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)As per static analysis hint.
🧹 Nitpick comments (10)
client-go/version/version_test.go (1)
9-19: Consider a more descriptive test name.While the test logic is correct and properly handles the package-level variable modification, consider naming it following the guideline format:
TestUserAgent_WithCustomVersion_ReturnsFormattedStringfor better clarity.As per coding guidelines, test names should follow the format:
TestFunctionName_Scenario_ExpectedBehavior.🔎 Optional improvement
-func TestUserAgent(t *testing.T) { +func TestUserAgent_WithCustomVersion_ReturnsFormattedString(t *testing.T) {api/device/v1alpha1/register.go (1)
25-27: Add godoc comment for exported function.The exported
Resourcefunction lacks documentation explaining its purpose in mapping resource names to GroupResource.As per coding guidelines.
🔎 Suggested documentation
+// Resource takes an unqualified resource and returns a GroupResource with the correct group. func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() }client-go/nvgrpc/client_conn.go (1)
25-26: Godoc should mention insecure transport.The function uses
insecure.NewCredentials()(line 44) for Unix domain sockets, but the documentation doesn't clarify that TLS is not enabled. Consider noting this is suitable for local/trusted connections.🔎 Suggested documentation
-// ClientConnFor creates a new gRPC connection using the provided configuration and options. +// ClientConnFor creates a new gRPC connection using the provided configuration and options. +// It uses insecure transport credentials suitable for Unix domain sockets and local connections.client-go/hack/overlays/client/versioned/clientset.go (1)
46-65: Consider validating config in NewForConfigAndClient.While the nil check is present, the config content isn't validated. Since
nvgrpc.ClientConnForisn't called in this path, invalid config values could propagate to the device client creation.🔎 Proposed validation addition
func NewForConfigAndClient(c *nvgrpc.Config, conn grpc.ClientConnInterface) (*Clientset, error) { if c == nil { return nil, fmt.Errorf("config cannot be nil") } + if err := c.Validate(); err != nil { + return nil, err + } if conn == nil { return nil, fmt.Errorf("gRPC connection cannot be nil") }client-go/nvgrpc/options_test.go (1)
25-65: LGTM: Comprehensive option testing.The test validates logger assignment and interceptor appending, including multiple interceptors. The use of subtests improves test organization.
While the current assertions work, consider using
testify/assertfor more descriptive failure messages in future tests, per coding guidelines.client-go/nvgrpc/config_test.go (1)
20-120: Well-structured tests with comprehensive coverage.The table-driven tests effectively cover Target precedence, UserAgent defaults, and validation logic. The use of
t.Setenv()for environment variable testing is correct.Optional: Consider using testify for assertions
Per coding guidelines, you may want to use
testify/assertortestify/requirefor cleaner assertions:+import ( + "testing" + "github.com/stretchr/testify/require" +) func TestConfig_Default_TargetPrecedence(t *testing.T) { // ... test table ... for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Setenv(NvidiaDeviceAPITargetEnvVar, tt.envTarget) cfg := &Config{Target: tt.argTarget} cfg.Default() - if cfg.Target != tt.wantTarget { - t.Errorf("Target = %q, want %q", cfg.Target, tt.wantTarget) - } + require.Equal(t, tt.wantTarget, cfg.Target) }) } }However, the current implementation is also acceptable.
api/device/v1alpha1/gpu_conversion_test.go (1)
30-153: Solid conversion tests with good nil-safety and round-trip verification.The tests correctly use
protocmp.Transform()for protobuf comparisons and verify key behaviors like Name lowercasing and ResourceVersion propagation.Optional: More descriptive test names per coding guidelines
Per the coding guideline "Name Go tests descriptively using format:
TestFunctionName_Scenario_ExpectedBehavior", consider renaming:-func TestGPUConversion(t *testing.T) { +func TestGPUConversion_RoundTrip_PreservesMetadataAndFields(t *testing.T) { -func TestGPUListConversion(t *testing.T) { +func TestGPUListConversion_RoundTrip_PreservesListMetadataAndItems(t *testing.T) {This makes the test intent more explicit at a glance.
client-go/DEVELOPMENT.md (1)
77-77: Minor style improvement.The phrase "inside of" is redundant. Simply "inside" is preferred.
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.client-go/nvgrpc/interceptors_test.go (1)
29-66: Remove unusedexpectedCodefield from test struct.The
expectedCodefield (line 35) is defined in the test cases but never used in assertions. This is dead code that may confuse future maintainers.🔎 Suggested fix
tests := []struct { name string method string log bool invokerErr error - expectedCode codes.Code }{ - {"Returns OK code for successful call", "/svc/success", true, nil, codes.OK}, - {"Returns internal status error on internal error", "/svc/internal_error", true, status.Error(codes.Internal, "fail"), codes.Internal}, - {"Returns canceled status error when canceled", "/svc/cancel", true, status.Error(codes.Canceled, ""), codes.Canceled}, - {"Returns deadline exceeded status error on timeout", "/svc/timeout", true, status.Error(codes.DeadlineExceeded, ""), codes.DeadlineExceeded}, - {"Does not log if level too low", "/svc/skip_log", false, nil, codes.OK}, + {"Returns OK code for successful call", "/svc/success", true, nil}, + {"Returns internal status error on internal error", "/svc/internal_error", true, status.Error(codes.Internal, "fail")}, + {"Returns canceled status error when canceled", "/svc/cancel", true, status.Error(codes.Canceled, "")}, + {"Returns deadline exceeded status error on timeout", "/svc/timeout", true, status.Error(codes.DeadlineExceeded, "")}, + {"Does not log if level too low", "/svc/skip_log", false, nil}, }This also allows removing the
codesimport if it becomes unused.client-go/nvgrpc/watcher_test.go (1)
31-177: Good test coverage, consider using testify for assertions.The tests comprehensively cover normal operation, error handling, and lifecycle management. Test structure and naming are clear.
Consider adopting
testify/assertandtestify/requirefor more expressive assertions, as per coding guidelines. For example:import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // Instead of: if len(got) != len(wantTypes) { t.Fatalf("got %d events, want %d", len(got), len(wantTypes)) } // Use: require.Len(t, got, len(wantTypes), "unexpected event count") assert.Equal(t, wantTypes[i], ev.Type, "event %d type mismatch", i)As per coding guidelines, prefer testify for test assertions.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (47)
.coderabbit.yaml(1 hunks).gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/version/version.goapi/device/v1alpha1/register.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/streaming-daemon/main.goclient-go/nvgrpc/interceptors.goclient-go/examples/basic-client/main.goclient-go/nvgrpc/client_conn_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/nvgrpc/config_test.goclient-go/examples/fake-server/main.goclient-go/nvgrpc/client_conn.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/nvgrpc/interceptors_test.goclient-go/version/version_test.goclient-go/nvgrpc/options.goapi/device/v1alpha1/doc.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/config.goapi/device/v1alpha1/converter.goclient-go/examples/controller-shim/main.goapi/device/v1alpha1/gpu_conversion.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goapi/device/v1alpha1/gpu_types.goclient-go/nvgrpc/watcher_test.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/config_test.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/nvgrpc/interceptors_test.goclient-go/version/version_test.goclient-go/nvgrpc/watcher_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
client-go/go.modapi/go.mod
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
.versions.yamlclient-go/go.modapi/go.modapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
.versions.yamlclient-go/examples/basic-client/README.mdclient-go/examples/basic-client/main.goclient-go/nvgrpc/client_conn_test.goclient-go/hack/boilerplate_overlay.go.txtclient-go/go.modclient-go/README.mdapi/go.modclient-go/hack/apply-overlays.shclient-go/examples/README.mdclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/Makefileclient-go/DEVELOPMENT.md.gitignore
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
.versions.yamlclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/client_conn_test.goclient-go/go.modclient-go/version/version_test.goclient-go/examples/README.mdclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go.gitignore
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.versions.yaml.gitignore
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
api/hack/boilerplate.go.txtclient-go/hack/boilerplate_overlay.go.txtclient-go/hack/boilerplate.go.txt
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/version/version.goclient-go/nvgrpc/client_conn_test.goclient-go/go.modclient-go/nvgrpc/options.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/version/version.goclient-go/nvgrpc/options.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `testify/assert` and `testify/require` for assertions in Go tests
Applied to files:
client-go/nvgrpc/client_conn_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/nvgrpc/client_conn_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
client-go/nvgrpc/client_conn_test.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/version/version_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Aim for >80% test coverage on critical paths in Go code
Applied to files:
client-go/nvgrpc/client_conn_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
client-go/go.modapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/go.modclient-go/nvgrpc/watcher.goapi/go.modclient-go/examples/controller-shim/main.go
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/examples/controller-shim/main.go
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
🧬 Code graph analysis (18)
api/device/v1alpha1/register.go (1)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
client-go/hack/overlays/client/versioned/integration_test.go (4)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
client-go/nvgrpc/config_test.go (2)
client-go/nvgrpc/config.go (3)
DefaultNvidiaDeviceAPISocket(31-31)NvidiaDeviceAPITargetEnvVar(28-28)Config(41-49)client-go/version/version.go (1)
UserAgent(28-35)
client-go/nvgrpc/client_conn.go (4)
client-go/nvgrpc/config.go (3)
Config(41-49)DefaultKeepAliveTime(34-34)DefaultKeepAliveTimeout(37-37)client-go/nvgrpc/options.go (1)
DialOption(23-23)client-go/version/version.go (1)
UserAgent(28-35)client-go/nvgrpc/interceptors.go (2)
NewLatencyUnaryInterceptor(28-59)NewLatencyStreamInterceptor(62-92)
api/device/v1alpha1/gpu_conversion_test.go (1)
api/device/v1alpha1/gpu_conversion.go (4)
FromProto(25-32)ToProto(35-40)FromProtoList(43-48)ToProtoList(51-56)
client-go/nvgrpc/interceptors_test.go (1)
client-go/nvgrpc/interceptors.go (2)
NewLatencyUnaryInterceptor(28-59)NewLatencyStreamInterceptor(62-92)
client-go/version/version_test.go (1)
client-go/version/version.go (2)
GitVersion(25-25)UserAgent(28-35)
client-go/nvgrpc/config.go (1)
client-go/version/version.go (1)
UserAgent(28-35)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/examples/controller-shim/main.go (5)
client-go/hack/overlays/client/versioned/clientset.go (2)
New(79-83)NewForConfig(32-44)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(58-63)NewForConfig(27-35)client-go/nvgrpc/config.go (1)
Config(41-49)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
api/device/v1alpha1/gpu_conversion.go (2)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (6)
DeviceV1alpha1Interface(9-12)DeviceV1alpha1Client(15-18)NewForConfig(27-35)NewForConfigAndClient(39-44)NewForConfigOrDie(48-55)New(58-63)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (4)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (2)
GPUsGetter(17-19)GPUInterface(22-27)client-go/hack/overlays/client/versioned/clientset.go (3)
NewForConfig(32-44)NewForConfigAndClient(48-65)New(79-83)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (5)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
DeviceV1alpha1Client(15-18)api/device/v1alpha1/gpu_conversion.go (2)
FromProto(25-32)FromProtoList(43-48)client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 GitHub Actions: Lint and Test
client-go/go.mod
[error] 1-1: gomod-lint failed: Invalid module version for github.com/nvidia/nvsentinel/api. Current: v0.0.0-00010101000000-000000000000; Expected: v0.0.0. Local modules should use v0.0.0 (no timestamp).
api/go.mod
[error] 1-1: Command failed: make gomod-lint. gomod-lint reported incorrect version for github.com/nvidia/nvsentinel/api: Current: v0.0.0-00010101000000-000000000000, Expected: v0.0.0. Local modules should use v0.0.0 (no timestamp).
api/Makefile
[error] 1-1: License header linting failed. Command 'make license-headers-lint' exited with code 2.
client-go/Makefile
[error] 1-1: License header linting failed. Command 'make license-headers-lint' exited with code 2.
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
⏰ 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). (3)
- GitHub Check: E2E Tests (AMD64 + PostgreSQL)
- GitHub Check: E2E Tests (AMD64 + MongoDB)
- GitHub Check: E2E Tests (ARM64 + MongoDB)
🔇 Additional comments (49)
.gitignore (1)
18-18: Consistent and appropriate addition.The new entry
client-go/bin/*correctly mirrors the existingapi/bin/*pattern and aligns with the PR's introduction of a new client-go module with generated code and build artifacts. The placement within the Go section is logical and follows established conventions.client-go/hack/boilerplate.go.txt (1)
1-13: ✓ Correct Apache 2.0 license header boilerplate.The boilerplate template is well-formed, uses proper Go comment syntax, includes the current year (2025) in the copyright notice, and provides the complete Apache 2.0 license text with correct URL and disclaimers. This file will serve correctly as a template for prepending license headers to generated code.
api/hack/boilerplate.go.txt (1)
1-13: LGTM!The Apache 2.0 license header is correctly formatted and will serve as the boilerplate template for code generation tools.
.coderabbit.yaml (1)
19-24: LGTM!The path filters correctly exclude generated code from review (protobuf bindings, deepcopy/conversion code, generated clientsets, listers, and informers). This aligns with the PR's code generation strategy and follows best practices.
client-go/examples/basic-client/README.md (1)
1-28: LGTM!The README provides clear, comprehensive documentation for the basic client reference implementation. The structure, content, and examples are well-organized and align with the PR's objectives.
client-go/examples/README.md (1)
1-38: LGTM!The examples README provides an excellent overview with a well-structured table categorizing examples by complexity and focus. The prerequisites and running instructions are clear and complete.
client-go/examples/fake-server/README.md (1)
1-18: LGTM!The fake server README clearly documents its purpose, usage, and behavior. The explanation of the 2-second status toggle is particularly useful for understanding how Watch streams and controllers can be tested locally.
client-go/version/version.go (1)
22-35: LGTM!The GitVersion variable and UserAgent function are well-documented and correctly implemented. The build-time override pattern using ldflags is clearly explained and follows standard Go practices.
client-go/nvgrpc/interceptors.go (2)
27-59: LGTM: Well-structured unary interceptor.The latency interceptor correctly measures RPC duration, propagates errors, and uses appropriate verbosity levels for different scenarios.
61-92: LGTM: Stream interceptor follows the same pattern.The stream interceptor mirrors the unary pattern with appropriate verbosity thresholds for stream establishment.
client-go/nvgrpc/options.go (1)
22-50: LGTM: Clean functional options implementation.The DialOption pattern is correctly implemented with clear documentation for all exported functions. The interceptor appending allows proper chaining.
client-go/nvgrpc/config.go (1)
26-89: LGTM: Robust configuration with proper defaults.The Config implementation correctly:
- Documents all exported constants and types
- Uses environment variables for flexibility
- Provides safe defaults including a discard logger
- Validates required fields with clear error messages
client-go/nvgrpc/client_conn.go (1)
27-71: LGTM: Correct implementation with proper isolation.The function correctly:
- Creates a shallow copy to avoid mutating the caller's Config
- Applies dial options and defaults
- Validates configuration before dialing
- Builds interceptor chains with latency monitoring first
- Wraps errors with context
client-go/examples/fake-server/main.go (2)
40-82: LGTM: Clean server setup with proper shutdown handling.The main function correctly:
- Reads socket path from environment with sensible default
- Removes stale sockets before listening
- Registers signal handlers for graceful shutdown
- Cleans up socket on exit
196-246: LGTM: WatchGpus correctly implements streaming pattern.The watch implementation:
- Sends initial ADDED events for all GPUs under lock
- Registers listener for future updates
- Properly cleans up listener on stream close
- Handles context cancellation correctly
client-go/examples/streaming-daemon/README.md (1)
1-30: LGTM: Clear documentation for streaming patterns.The README effectively documents:
- Production-grade patterns for long-lived connections
- Key concepts (manual connection management, interceptors, stream processing, context handling)
- Running instructions with correct path to fake-server
- Expected output matching the fake-server implementation
client-go/hack/overlays/client/versioned/clientset.go (3)
26-44: LGTM: Proper config validation and shallow copy.The nil check, shallow copy to prevent mutation, and delegation to
nvgrpc.ClientConnFor(which validates the config) follow the correct pattern.
67-76: LGTM: Standard OrDie pattern.The panic-on-error behavior is appropriate for this constructor variant.
78-83: LGTM: Direct connection constructor.The implementation correctly creates a clientset from an existing connection, with logging disabled by default.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (4)
9-12: LGTM: Clean interface definition.The interface correctly defines the contract for the v1alpha1 device client.
24-35: LGTM: Proper delegation with validated config.The shallow copy and validation via
nvgrpc.ClientConnForare correct.
46-55: LGTM: Standard OrDie pattern.The panic-on-error behavior is appropriate for this constructor variant.
65-73: LGTM: Defensive nil check in accessor.The nil check on the receiver prevents potential panics and follows defensive programming practices.
client-go/hack/boilerplate_overlay.go.txt (1)
1-16: LGTM: Proper boilerplate header.The Apache 2.0 license header and generated code notice are correctly formatted.
client-go/examples/controller-shim/README.md (1)
1-42: LGTM: Clear and comprehensive documentation.The README effectively explains the hybrid reconciliation pattern, informer injection, and controller-runtime integration. The running instructions and expected output are helpful for users.
client-go/hack/apply-overlays.sh (1)
1-29: LGTM: Robust error handling and clear logic.The script correctly uses
set -euo pipefail, validates prerequisites, and processes overlays with proper path manipulation. The addressed past review comment about error handling has been resolved.api/device/v1alpha1/doc.go (1)
15-19: LGTM: Proper API group documentation.The Kubebuilder marker and package documentation correctly define the v1alpha1 API group with clear descriptions of GPU resources and conversion functions.
client-go/examples/basic-client/main.go (1)
30-80: Clean example demonstrating basic client usage.The example effectively shows List, Get, and condition inspection patterns. Good use of
meta.IsStatusConditionTrue()for checking conditions and proper error handling throughout.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
9-27: Clean adapter implementation for gRPC stream to runtime.Object conversion.The adapter correctly delegates to the underlying stream for
Recv()andCloseSend(), and usesFromProto()for type conversion. The nil-handling is safe sinceFromProto()already checks for nil input.client-go/DEVELOPMENT.md (1)
1-105: Comprehensive and well-organized development guide.The documentation clearly explains the code generation workflow, overlay pattern, and housekeeping commands. The Mermaid diagram effectively visualizes the generation pipeline.
client-go/README.md (1)
1-96: Excellent documentation for the client-go SDK.The README provides clear explanations of features, installation, quick start examples, and deployment patterns. The warning about experimental status is appropriately prominent, and the examples table effectively guides users to the right integration pattern.
client-go/examples/streaming-daemon/main.go (1)
36-144: Excellent demonstration of advanced gRPC patterns.The example effectively showcases custom interceptors for tracing and monitoring, manual connection lifecycle management, and comprehensive watch stream handling including error cases and context timeouts. Good use of
deferfor cleanup and proper channel handling.api/device/v1alpha1/gpu_conversion.go (1)
15-56: Well-designed conversion helper layer.The helpers provide a clean public API with proper nil-safety. The build tag
!govertercorrectly excludes this file during code generation, and the pointer handling differences betweenFromProtoandFromProtoListcorrectly match the underlying converter interface signatures.client-go/go.mod (1)
1-15: Module structure looks good.The module declaration, Go version, replace directive, and direct dependencies are well-organized. The Kubernetes dependency versions are aligned at v0.34.1, and the controller-runtime version is appropriate.
client-go/nvgrpc/interceptors_test.go (1)
68-103: LGTM!The streaming interceptor test is well-structured with appropriate coverage of success, error, and log-level gating scenarios. The error propagation assertion using
errors.Isis correct.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
17-24: LGTM on ClientConn implementation.The
ClientConn()method is appropriately documented, explaining that the fake usesObjectTrackerinstead of a real gRPC connection. Returningnilis acceptable here since the fake implementation doesn't need an actual connection.client-go/examples/controller-shim/main.go (2)
64-105: Manager configuration is well-designed for hybrid reconciliation.The custom
MapperProvidercorrectly registers GPU as a root-scoped resource, and theNewInformercallback appropriately injects the gRPC-backed informer for GPU objects while falling back to standard informers for other types. The indexer merging logic correctly handles conflicts.
123-145: LGTM!The
GPUReconcilerfollows controller-runtime best practices: proper structured logging, gracefulNotFoundhandling withclient.IgnoreNotFound, and standard controller builder pattern inSetupWithManager.client-go/hack/overlays/client/versioned/integration_test.go (3)
33-63: Well-structured test harness setup.The test correctly sets up an in-process gRPC server using
bufconn, creates a mock GPU server, and establishes a clientset connection. This pattern enables fast, isolated integration testing without network overhead.
64-129: LGTM on Get, List, and Watch tests.The subtests properly exercise the core clientset operations with appropriate assertions and timeout handling. The Watch test correctly validates both initial snapshot and live event propagation.
255-337: LGTM on mock server implementation.The mock server is well-designed with proper thread-safety using
sync.RWMutex, correct context handling in the streamingWatchGpusmethod, and a cleansendEventhelper for test control. The initial snapshot followed by live event streaming correctly mimics Kubernetes watch semantics.api/proto/device/v1alpha1/gpu.proto (2)
53-78: LGTM on Gpu and GpuList message structure.The restructured messages follow the Kubernetes Resource Model pattern correctly with
ObjectMeta/ListMetaat field 1, and the documentation clearly explains the naming conventions. This aligns well with client-go expectations.
151-167: LGTM on request message updates.Adding
resource_versiontoListGpusRequestandWatchGpusRequestenables proper Kubernetes-style watch semantics, allowing clients to list/watch from a specific version and resume watches after disconnection.api/device/v1alpha1/gpu_types.go (1)
15-71: LGTM! Well-structured Kubernetes CRD types.The GPU resource types follow Kubernetes conventions correctly with proper TypeMeta/ObjectMeta embedding, appropriate code-generation markers for client-gen and deepcopy-gen, and clear field documentation. The non-namespaced resource configuration is appropriate for node-local GPU resources.
client-go/nvgrpc/watcher.go (1)
15-170: LGTM! Solid watch implementation with proper lifecycle management.The watcher correctly implements Kubernetes watch semantics with:
- Idempotent shutdown via
sync.Once- Proper context cancellation and cleanup
- Correct gRPC status code mapping (lines 147-150 map codes to 410 Expired for informer re-list)
- Structured logging at appropriate verbosity levels
The implementation follows the coding guidelines for context cancellation and shutdown handling.
api/device/v1alpha1/converter.go (1)
23-133: LGTM! Well-structured converter interface with proper code-generation annotations.The Converter interface correctly uses
SchemeGroupVersion.String()for APIVersion (lines 110, 118), ensuring the full "device.nvidia.com/v1alpha1" format. The goverter annotations properly map fields between protobuf and Kubernetes types, and timestamp conversion handles nil values safely.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
1-87: LGTM! Clean client implementation following Kubernetes patterns.The GPU client correctly implements Kubernetes client-go conventions with:
- Proper context propagation and cancellation cleanup
- Structured logging at appropriate verbosity levels (V(4-6))
- Resource version handling for optimistic concurrency
- Correct error handling with early cleanup in Watch method
The implementation uses
client-gofor Kubernetes API interactions as required by coding guidelines, andgpuStreamAdapterproperly implements thenvgrpc.Sourceinterface withNext()andClose()methods.client-go/Makefile (1)
19-213: Well-structured client-go build system with proper code generation orchestration.The Makefile correctly orchestrates client-gen, lister-gen, and informer-gen with proper tool versioning and overlay application. The version embedding via
LDFLAGSenables runtime version reporting. The boilerplate file (hack/boilerplate.go.txt) contains a valid Apache 2.0 license header that will be applied to generated code.api/Makefile (1)
19-206: Well-structured build workflow with comprehensive code generation.The Makefile properly orchestrates protobuf generation, deepcopy generation, and conversion generation with per-version iteration. Tool versioning from
.versions.yamland thego-install-toolmacro withGOTOOLCHAINsupport ensure reproducible builds. The file has the required Apache 2.0 license header and follows project conventions.
1072d57 to
3891ded
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (8)
client-go/version/version.go (1)
15-15: Add package-level godoc comment.The coding guidelines require package-level godoc for all Go packages. Add a package comment describing the purpose of this package.
As per coding guidelines, package-level godoc is required for all Go packages.
🔎 Suggested addition
+// Package version provides build-time version information and user-agent +// string generation for the nvidia-device-api-client. package versionclient-go/Makefile (1)
187-187: Declare thetoolstarget as PHONY.The
toolstarget should be declared.PHONYsince it doesn't produce a file output and is used as a convenience alias for tool binaries.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)client-go/examples/controller-shim/main.go (1)
60-64: The informer factory is still never started (unresolved from previous review).The comment on line 62 states "the Manager will start the injected informer," but this is incorrect. Controller-runtime only starts informers created through its own cache. The gRPC-backed
factorymust be started explicitly withfactory.Start(stopCh), otherwise the cache never populates and reconciliation fails silently.Suggested fix
Start the factory after creating the manager but before starting it:
if err != nil { setupLog.Error(err, "unable to create manager") os.Exit(1) } + // Start the gRPC-backed informer factory. The manager does NOT automatically + // start externally created informers; they must be started explicitly. + ctx := ctrl.SetupSignalHandler() + go factory.Start(ctx.Done()) + + // Wait for the informer cache to sync before starting reconciliation. + synced := factory.WaitForCacheSync(ctx.Done()) + for gvk, isSynced := range synced { + if !isSynced { + setupLog.Error(nil, "failed to sync cache for resource", "gvk", gvk) + os.Exit(1) + } + } + if err = (&GPUReconciler{Then update line 116 to reuse the context:
- ctx := ctrl.SetupSignalHandler() - setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil {Based on learnings, use meaningful variable names such as
syncedfor cache sync checks.client-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorf(or anytmethod) from a goroutine is unsafe and can cause race conditions or panics if the test completes before the goroutine executes. Consider using an error channel to capture the error and check it in the main test goroutine, or simply ignore the error sincec.Startblocks until context cancellation andWaitForCacheSyncwill catch initialization failures.Based on learnings, proper shutdown handling with context cancellation should be implemented in Go code.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
37-44: Validate config inNewForConfigAndClient.
NewForConfigAndClientaccepts a config but doesn't validate it, potentially allowing invalid configurations (e.g., empty target, invalid logger) to propagate silently. Consider validating the config before constructing the client.🔎 Proposed validation addition
func NewForConfigAndClient(c *nvgrpc.Config, conn grpc.ClientConnInterface) (*DeviceV1alpha1Client, error) { + if err := c.Validate(); err != nil { + return nil, err + } return &DeviceV1alpha1Client{ conn: conn, logger: c.GetLogger().WithName("device.v1alpha1"), }, nil }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-11: Add package-level godoc comment.The coding guidelines require package-level documentation for all Go packages. Based on learnings, package-level godoc is required for all Go packages.
🔎 Suggested documentation
+// Package fake provides fake implementations of the device v1alpha1 client +// for testing purposes. These fakes use an in-memory ObjectTracker instead +// of actual gRPC connections. package fake
13-15: Add function comment for exported method.The coding guidelines require function comments for all exported Go functions. Based on learnings, function comments are required for all exported Go functions.
🔎 Suggested documentation
+// GPUs returns a fake GPUInterface for testing GPU operations +// without requiring an actual gRPC connection. func (c *FakeDeviceV1alpha1) GPUs() v1alpha1.GPUInterface { return newFakeGPUs(c) }client-go/examples/fake-server/main.go (1)
190-203: PopulateListMeta.ResourceVersionfor List-then-Watch pattern.The
GpuListresponse doesn't includemetadata.resource_version, which is needed for clients to establish a watch from a consistent point (List-then-Watch pattern). Consider tracking and populating a list-level resource version.🔎 Suggested fix
func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { s.mu.RLock() defer s.mu.RUnlock() + // Find the highest ResourceVersion among all GPUs for list consistency + maxRv := "1" + for _, gpu := range s.gpus { + if gpu.ResourceVersion > maxRv { + maxRv = gpu.ResourceVersion + } + } + gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: maxRv, + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), } for _, gpu := range s.gpus { gpuList.Items = append(gpuList.Items, devicev1alpha1.ToProto(&gpu)) } return &pb.ListGpusResponse{GpuList: gpuList}, nil }
🧹 Nitpick comments (5)
client-go/nvgrpc/config_test.go (2)
20-120: Use testify assertions per coding guidelines.The tests currently use basic
ifstatements witht.Errorffor assertions. According to the coding guidelines, Go tests should usetestify/assertandtestify/requirefor assertions.🔎 Refactor to use testify/assert
Import testify at the top of the file:
import ( "testing" + + "github.com/stretchr/testify/assert" )Then refactor the assertions. For example, in
TestConfig_Default_TargetPrecedence:t.Run(tt.name, func(t *testing.T) { t.Setenv(NvidiaDeviceAPITargetEnvVar, tt.envTarget) cfg := &Config{Target: tt.argTarget} cfg.Default() - if cfg.Target != tt.wantTarget { - t.Errorf("Target = %q, want %q", cfg.Target, tt.wantTarget) - } + assert.Equal(t, tt.wantTarget, cfg.Target) })Similarly for
TestConfig_Default_UserAgent:t.Run("Populates default UserAgent if empty", func(t *testing.T) { cfg := &Config{} cfg.Default() - if cfg.UserAgent == "" { - t.Error("UserAgent should have been populated with version-based default") - } + assert.NotEmpty(t, cfg.UserAgent, "UserAgent should have been populated with version-based default") }) t.Run("Preserves custom UserAgent", func(t *testing.T) { custom := "my-custom-agent/1.0" cfg := &Config{UserAgent: custom} cfg.Default() - if cfg.UserAgent != custom { - t.Errorf("UserAgent = %q, want %q", cfg.UserAgent, custom) - } + assert.Equal(t, custom, cfg.UserAgent) })And for
TestConfig_Validate:for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := tt.cfg.Validate() - if (err != nil) != tt.wantErr { - t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) - } + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } }) }As per coding guidelines, use testify for assertions in Go tests.
62-69: Consider verifying the actual default UserAgent value.The test checks that
UserAgentis not empty after callingDefault(), but doesn't verify it matches the expected default fromversion.UserAgent(). This would make the test more precise and catch regressions in the default value logic.🔎 Suggested enhancement
+import ( + "github.com/NVIDIA/nvidia-device-api-go/client-go/version" +) + t.Run("Populates default UserAgent if empty", func(t *testing.T) { cfg := &Config{} cfg.Default() - if cfg.UserAgent == "" { - t.Error("UserAgent should have been populated with version-based default") - } + expected := version.UserAgent() + if cfg.UserAgent != expected { + t.Errorf("UserAgent = %q, want %q", cfg.UserAgent, expected) + } })client-go/DEVELOPMENT.md (1)
10-11: Optional: Minor style and formatting improvements.Two minor style issues were detected:
- Lines 10-11: Inconsistent list indentation (expected 2 spaces, actual 4).
- Line 77: "inside of" can be simplified to "inside" for conciseness.
🔎 Proposed fixes
Fix list indentation:
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)Simplify phrasing:
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.Also applies to: 77-77
api/Makefile (1)
36-36: Optional: Add space after#in comment.Line 36 is missing a space after the
#symbol, making it inconsistent with the other comments in the file.🔎 Proposed fix
-#Helper for tools that need comma-separated package paths +# Helper for tools that need comma-separated package pathsclient-go/nvgrpc/watcher_test.go (1)
154-177: Avoidtime.Sleepin tests for synchronization.Line 160 uses
time.Sleep(10 * time.Millisecond)to "allow the receive loop to start." This introduces flakiness and slows down tests. Consider using synchronization primitives (e.g., a channel signal from the watcher's receive loop) or relying on the existing timeout-based assertions.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (47)
.coderabbit.yaml(1 hunks).gitignore(1 hunks).versions.yaml(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- api/device/v1alpha1/gpu_conversion_test.go
- client-go/examples/controller-shim/README.md
- api/hack/boilerplate.go.txt
🚧 Files skipped from review as they are similar to previous changes (21)
- client-go/examples/basic-client/README.md
- client-go/version/version_test.go
- client-go/nvgrpc/client_conn.go
- client-go/go.mod
- client-go/nvgrpc/interceptors_test.go
- api/proto/device/v1alpha1/gpu.proto
- .gitignore
- client-go/nvgrpc/config.go
- client-go/nvgrpc/options.go
- api/device/v1alpha1/doc.go
- api/go.mod
- client-go/examples/README.md
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
- client-go/hack/boilerplate.go.txt
- client-go/hack/boilerplate_overlay.go.txt
- .versions.yaml
- client-go/examples/streaming-daemon/README.md
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
- api/device/v1alpha1/register.go
- client-go/hack/apply-overlays.sh
- client-go/nvgrpc/client_conn_test.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/version/version.goclient-go/nvgrpc/options_test.goapi/device/v1alpha1/gpu_conversion.goclient-go/nvgrpc/config_test.goclient-go/examples/streaming-daemon/main.goclient-go/examples/fake-server/main.goclient-go/nvgrpc/interceptors.goapi/device/v1alpha1/gpu_types.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/integration_test.goapi/device/v1alpha1/converter.goclient-go/nvgrpc/watcher.goclient-go/examples/basic-client/main.goclient-go/nvgrpc/watcher_test.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/options_test.goclient-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.go
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/examples/fake-server/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/examples/basic-client/main.goclient-go/README.mdclient-go/DEVELOPMENT.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
api/Makefile
🧬 Code graph analysis (10)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
api/device/v1alpha1/gpu_conversion.go (2)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/nvgrpc/config_test.go (2)
client-go/nvgrpc/config.go (3)
DefaultNvidiaDeviceAPISocket(31-31)NvidiaDeviceAPITargetEnvVar(28-28)Config(41-49)client-go/version/version.go (1)
UserAgent(28-35)
client-go/examples/fake-server/main.go (3)
client-go/nvgrpc/config.go (2)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (6)
DeviceV1alpha1Interface(9-12)DeviceV1alpha1Client(15-18)NewForConfig(27-35)NewForConfigAndClient(39-44)NewForConfigOrDie(48-55)New(58-63)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/examples/controller-shim/main.go (4)
client-go/hack/overlays/client/versioned/clientset.go (1)
New(79-83)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
New(58-63)client-go/nvgrpc/config.go (3)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)Config(41-49)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/examples/basic-client/main.go (3)
client-go/hack/overlays/client/versioned/clientset.go (2)
New(79-83)NewForConfig(32-44)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(58-63)NewForConfig(27-35)client-go/nvgrpc/config.go (3)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)Config(41-49)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (32)
client-go/nvgrpc/config_test.go (1)
1-120: Well-structured test file with comprehensive coverage.The tests follow good practices:
- Table-driven tests for scenarios with multiple inputs
- Subtests using
t.Runfor logical grouping- Proper use of
t.Setenvfor environment variable testing- Clear test naming and scenarios
The test coverage for
Config.Default()andConfig.Validate()is comprehensive, covering target precedence, user agent defaulting, and validation scenarios..coderabbit.yaml (1)
19-24: LGTM! Well-organized ignore patterns for generated code.The path_filters appropriately exclude generated artifacts (protobuf bindings, deepcopy/conversion helpers, clientset, listers, and informers) from auto-review, reducing noise while maintaining review coverage on handwritten code.
client-go/nvgrpc/options_test.go (1)
25-65: LGTM! Well-structured test for option composition.The test correctly validates DialOption behavior, including logger assignment and multiple interceptor appends. The use of subtests keeps the assertions organized.
client-go/hack/overlays/client/versioned/integration_test.go (4)
33-72: LGTM! Clean test setup and Get subtest.The bufconn-based in-process gRPC server setup is well-structured, and the Get subtest correctly validates basic retrieval functionality.
74-129: LGTM! Comprehensive List and Watch subtests.Both subtests correctly validate their respective operations, including initial snapshots and live event handling in the Watch flow.
131-182: LGTM! Proper informer lifecycle and sync validation.The subtest correctly instantiates the informer before starting the factory, waits for cache sync, and uses polling to verify cache updates. This aligns with Kubernetes informer best practices.
254-336: LGTM! Well-implemented thread-safe mock server.The mock GPU server correctly implements concurrent access protection with RWMutex, handles initial snapshots, and properly manages context cancellation in the watch loop.
client-go/nvgrpc/interceptors.go (2)
27-59: LGTM! Well-structured unary interceptor.The latency interceptor correctly measures RPC duration, handles errors with appropriate logging levels (V(4) for cancellation, Error for failures, V(6) for success), and returns the original error without modification.
61-92: LGTM! Well-structured stream interceptor.The stream latency interceptor correctly measures stream establishment duration and uses appropriate logging levels (V(4) for cancellation and successful establishment, Error for failures).
api/device/v1alpha1/gpu_types.go (1)
21-71: LGTM! Well-defined Kubernetes CRD types.The GPU resource types follow Kubernetes API conventions with appropriate code generation markers (+genclient, +k8s:deepcopy-gen) and clear documentation. The non-namespaced, read-only design (onlyVerbs=get,list,watch) is appropriate for node-local device resources.
api/device/v1alpha1/gpu_conversion.go (1)
21-56: LGTM! Nil-safe conversion helpers with appropriate build tags.The conversion helpers correctly implement nil-safety and delegate to the generated ConverterImpl. The
!goverterbuild tag appropriately excludes this file from goverter's code generation phase to avoid circular dependencies.client-go/nvgrpc/watcher.go (4)
32-46: LGTM! Well-designed Source interface and Watcher type.The Source interface provides a clean abstraction for event streams, and the Watcher type correctly uses
sync.Onceto ensure idempotent shutdown, addressing previous race condition concerns.Based on learnings, proper shutdown handling with context cancellation is implemented in Go code.
48-76: LGTM! Proper initialization and idempotent shutdown.The NewWatcher constructor correctly initializes all fields and starts the receive loop. The Stop method is now idempotent using
sync.Once, which properly resolves the previous race condition concern with double-close protection.Based on learnings, proper shutdown handling with context cancellation is implemented in Go code.
83-136: LGTM! Robust receive loop with proper error handling.The receive loop correctly handles normal termination (EOF, Canceled), maps event types, and uses select to prevent sending to a closed channel. The defer ordering ensures proper cleanup sequence.
Based on learnings, proper shutdown handling with context cancellation is implemented in Go code.
138-170: LGTM! Correct gRPC-to-Kubernetes error translation.The sendError helper appropriately maps gRPC status codes to Kubernetes status codes, with the critical 410 Expired mapping for OutOfRange/ResourceExhausted/InvalidArgument that triggers informer re-list behavior.
client-go/examples/basic-client/main.go (1)
30-83: LGTM! Clean example demonstrating client usage.The example correctly demonstrates List, Get, and status inspection operations using the versioned clientset. The use of
nvgrpc.NvidiaDeviceAPITargetEnvVarandnvgrpc.DefaultNvidiaDeviceAPISocketconstants (lines 36-38) ensures consistency with library defaults.Based on learnings,
client-gois used for Kubernetes API interactions in Go code.client-go/nvgrpc/watcher_test.go (1)
179-239: LGTM!The test utilities (
FakeObjectandFakeSource) are well-designed. TheFakeSource.Close()method properly handles idempotent closure with a select statement to avoid double-close panics, and theNext()method correctly prioritizes error injection before events for deterministic test behavior.api/device/v1alpha1/converter.go (2)
23-104: LGTM!The
Converterinterface is well-structured with appropriate goverter directives for code generation. The field mappings (e.g.,Uuid↔UUID,Metadata↔ObjectMeta/ListMeta) align with protobuf and Kubernetes naming conventions, and thegoverter:ignoredirectives properly exclude protobuf internal fields and Kubernetes-specific metadata fields.
122-133: LGTM!The timestamp conversion helpers correctly handle nil protobuf timestamps by returning zero-valued
metav1.Time, and theToProtobufTimestampconversion properly wraps the Go time in a protobuf timestamp.client-go/examples/fake-server/README.md (1)
1-29: LGTM!The documentation is clear and comprehensive. It properly explains the
sudorequirement for the default socket path, provides instructions for running without root usingNVIDIA_DEVICE_API_TARGET, and describes the simulated behavior (8 GPUs with 2-second status toggles).client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
17-24: LGTM!The
ClientConn()method correctly returns a typed nil for the fake implementation, which is appropriate for testing scenarios where no actual gRPC connection is needed.client-go/examples/streaming-daemon/main.go (2)
37-77: LGTM!The initialization logic correctly uses
nvgrpc.DefaultNvidiaDeviceAPISocketas the default target, properly wires custom interceptors for tracing and watch monitoring, and establishes the gRPC connection with appropriate error handling and deferred cleanup.
99-146: LGTM!The watch stream handling is robust: it properly handles watch errors by checking for
watch.Errorevents and extractingmetav1.Status, performs type assertions on GPU objects, extracts readiness from conditions usingmeta.IsStatusConditionTrue, and gracefully shuts down on context cancellation.client-go/hack/overlays/client/versioned/clientset.go (2)
12-24: LGTM!The
InterfaceandClientsetstructure follows standard Kubernetes client-go patterns, and theDeviceV1alpha1()accessor properly exposes the typed client interface.
26-65: LGTM!The constructor pattern is well-designed:
NewForConfighandles connection creation and delegates toNewForConfigAndClient, both constructors properly validate nil parameters, and the shallow copy pattern prevents config mutation. The separation allows users to customize the connection (e.g., with interceptors) when needed.client-go/examples/fake-server/main.go (4)
42-91: LGTM!The main function properly handles socket path resolution using
nvgrpc.NvidiaDeviceAPITargetEnvVarandnvgrpc.DefaultNvidiaDeviceAPISocket, creates the socket directory with appropriate permissions, removes stale sockets, and implements graceful shutdown with signal handling and socket cleanup.
100-164: LGTM!The fake server initialization and simulation logic correctly create 8 GPUs with initial
ResourceVersion: "1", and thesimulateChangesgoroutine properly incrementsResourceVersionon each update (supporting Kubernetes watch semantics), toggles the Ready condition, updatesLastTransitionTime, and broadcasts changes to registered watch streams.
177-188: LGTM!The
GetGpuimplementation correctly searches the in-memory GPU slice and returns a propercodes.NotFoundgRPC error when the GPU is not found.
205-255: LGTM!The
WatchGpusimplementation correctly sends initial ADDED events for all GPUs, registers for ongoing updates, streams MODIFIED events to the client, and properly cleans up the listener registration on stream termination or context cancellation.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (3)
9-22: LGTM!The
DeviceV1alpha1Interfaceproperly exposes both theClientConn()accessor and theGPUsGetterinterface, and theDeviceV1alpha1Clientstruct correctly maintains the gRPC connection and logger fields. TheGPUs()method appropriately delegates tonewGPUs.
24-35: LGTM!The
NewForConfigconstructor correctly shallow-copies the config to prevent mutation, creates the gRPC connection vianvgrpc.ClientConnFor, and delegates toNewForConfigAndClientwith proper error propagation.
65-73: LGTM!The
ClientConn()method properly handles nil receivers and returns the underlying gRPC connection interface, following defensive coding practices.
3806f19 to
4f3e806
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
♻️ Duplicate comments (7)
client-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorffrom a goroutine is unsafe and can cause race conditions if the test completes before the goroutine executes. Use an error channel to safely propagate errors to the main test goroutine.🔎 Suggested fix using an error channel
+ errCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + errCh <- err } + close(errCh) }() + // Check for startup errors after sync + if !c.WaitForCacheSync(ctx) { + t.Fatal("Controller-runtime cache failed to sync") + } + + select { + case err := <-errCh: + if err != nil { + t.Fatalf("Cache failed to start: %v", err) + } + default: + } - - if !c.WaitForCacheSync(ctx) { - t.Fatal("Controller-runtime cache failed to sync") - }client-go/examples/controller-shim/main.go (3)
15-15: Add package-level documentation.As per coding guidelines, package-level godoc is required. This example demonstrates an important integration pattern.
Suggested addition
+// Package main demonstrates a controller-shim pattern that uses a gRPC-backed +// informer with controller-runtime to reconcile GPU resources over a Unix domain socket. +// This example shows how to inject a custom informer into the manager's cache to enable +// Kubernetes-style reconciliation loops without requiring a real API server. package main
130-147: Add godoc comments for exported methods.The exported methods
ReconcileandSetupWithManagerlack documentation. Coding guidelines require function comments for all exported Go functions.Suggested additions
+// Reconcile retrieves the requested GPU resource from the gRPC-backed cache +// and logs its name and UUID. It returns without error if the GPU is not found. func (r *GPUReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := ctrl.LoggerFrom(ctx) var gpu devicev1alpha1.GPU // The Get call is transparently routed through the injected gRPC-backed informer. if err := r.Get(ctx, req.NamespacedName, &gpu); err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } log.Info("Reconciled GPU", "name", gpu.Name, "uuid", gpu.Spec.UUID) return ctrl.Result{}, nil } +// SetupWithManager registers this reconciler with the provided manager, +// configuring it to watch GPU resources. func (r *GPUReconciler) SetupWithManager(mgr ctrl.Manager) error {
60-64: The informer factory is never started.The comment on line 62 states the Manager will start the injected informer, but controller-runtime only starts informers created through its own cache machinery. The gRPC-backed informer from
factoryneeds to be started explicitly; otherwise, the cache will never populate and reconciliation won't occur.Suggested fix
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + // Start the factory in the background. The informer must be running + // before the manager attempts to use the cache. + stopCh := make(chan struct{}) + go func() { + <-ctrl.SetupSignalHandler().Done() + close(stopCh) + }() + factory.Start(stopCh) + + // Wait for the cache to sync before proceeding. + if !toolscache.WaitForCacheSync(stopCh, gpuInformer.HasSynced) { + setupLog.Error(nil, "failed to sync informer cache") + os.Exit(1) + }api/proto/device/v1alpha1/gpu.proto (1)
35-37: Inconsistent indentation in comment blocks.Lines 35-37 use tabs while surrounding lines use spaces. This was flagged in a previous review but appears unaddressed.
Suggested fix
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/examples/fake-server/main.go (1)
190-203:ListMetais not populated in the response.The
GpuListresponse doesn't includemetadata.resource_version, which is needed for clients to establish a watch from a consistent point (List-then-Watch pattern). This was raised in a previous review but doesn't appear to be addressed yet.🔎 Suggested fix
func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { s.mu.RLock() defer s.mu.RUnlock() + // Compute highest resource version for list metadata + var maxRv int + for _, gpu := range s.gpus { + if rv, _ := strconv.Atoi(gpu.ResourceVersion); rv > maxRv { + maxRv = rv + } + } + gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: strconv.Itoa(maxRv), + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), }client-go/Makefile (1)
187-187: Declaretoolstarget as.PHONY.This issue was previously flagged. The
toolstarget should be declared.PHONYsince it doesn't produce a file named "tools".
🧹 Nitpick comments (9)
client-go/nvgrpc/interceptors_test.go (3)
17-27: Add testify imports per coding guidelines.The coding guidelines specify using
testify/assertandtestify/requirefor assertions in Go tests, but these packages are not imported. The current tests uset.Fatalffor assertions (lines 62, 99).As per coding guidelines, please add the testify imports and refactor assertions accordingly.
🔎 Proposed fix
import ( "context" "errors" "testing" "time" logr "github.com/go-logr/logr/testing" + "github.com/stretchr/testify/assert" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" )Then replace
t.Fatalfcalls withassert.ErrorIs:- if !errors.Is(err, tt.invokerErr) { - t.Fatalf("Returned error mismatch. Got %v, want %v", err, tt.invokerErr) - } + assert.ErrorIs(t, err, tt.invokerErr, "Returned error mismatch")
29-66: Remove unusedexpectedCodefield.The
expectedCodefield is defined in the test table (line 35) and populated for each test case, but it's never used in the test execution. This is dead code that should be removed to improve clarity.Additionally, the sleep logic on lines 54-56 when
!tt.logis unclear—it appears to simulate latency when logging is disabled, but the test doesn't verify any timing behavior or performance characteristics.🔎 Proposed cleanup
tests := []struct { name string method string log bool invokerErr error - expectedCode codes.Code }{ - {"Returns OK code for successful call", "/svc/success", true, nil, codes.OK}, - {"Returns internal status error on internal error", "/svc/internal_error", true, status.Error(codes.Internal, "fail"), codes.Internal}, - {"Returns canceled status error when canceled", "/svc/cancel", true, status.Error(codes.Canceled, ""), codes.Canceled}, - {"Returns deadline exceeded status error on timeout", "/svc/timeout", true, status.Error(codes.DeadlineExceeded, ""), codes.DeadlineExceeded}, - {"Does not log if level too low", "/svc/skip_log", false, nil, codes.OK}, + {"Returns OK code for successful call", "/svc/success", true, nil}, + {"Returns internal status error on internal error", "/svc/internal_error", true, status.Error(codes.Internal, "fail")}, + {"Returns canceled status error when canceled", "/svc/cancel", true, status.Error(codes.Canceled, "")}, + {"Returns deadline exceeded status error on timeout", "/svc/timeout", true, status.Error(codes.DeadlineExceeded, "")}, + {"Does not log if level too low", "/svc/skip_log", false, nil}, }If the sleep is intended to verify the interceptor doesn't add overhead when logging is disabled, consider adding a comment explaining this intent or removing it if not testing performance.
68-103: Clarify the purpose of sleep in non-logging test cases.Similar to the unary interceptor test, the sleep on lines 91-93 when
!tt.logis executed but its purpose is unclear. If this is intended to verify that the interceptor doesn't add significant overhead when logging is disabled, consider adding a comment to document this intent. Otherwise, if it's not testing performance characteristics, the sleep could be removed.💡 Example clarifying comment
streamer := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) { if !tt.log { + // Simulate minimal latency to verify interceptor overhead is negligible when logging disabled time.Sleep(1 * time.Millisecond) } return nil, tt.streamerErr }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
14-23: Consider adding context to stream errors.When
Recv()fails, the error is returned without additional context. Adding context would improve debuggability when stream errors occur.As per coding guidelines, wrap errors with context in Go code.
🔎 Proposed enhancement
func (a *gpuStreamAdapter) Next() (string, runtime.Object, error) { resp, err := a.stream.Recv() if err != nil { - return "", nil, err + return "", nil, fmt.Errorf("failed to receive from GPU watch stream: %w", err) } obj := devicev1alpha1.FromProto(resp.GetObject()) return resp.GetType(), obj, nil }Note: You'll need to import
fmtat the top of the file.client-go/DEVELOPMENT.md (2)
77-77: Minor style improvement: simplify "inside of" to "inside".The phrase "inside of" is redundant and can be simplified to "inside" for clearer writing.
🔎 Suggested fix
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.
10-11: Fix list indentation for markdown consistency.The nested list items use 4-space indentation instead of the expected 2 spaces, which may cause formatting issues in some markdown renderers.
🔎 Suggested fix
* **yq**: Required to parse version configuration. - * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)client-go/examples/basic-client/main.go (1)
15-15: Add package-level documentation.As per coding guidelines, package-level godoc is required for all Go packages. This example demonstrates the basic client usage pattern and should be documented.
Suggested addition
+// Package main demonstrates basic usage of the NVIDIA Device API client. +// It shows how to list GPUs, fetch individual GPU details, and inspect +// status conditions using the gRPC-backed versioned clientset. package mainclient-go/nvgrpc/watcher_test.go (1)
154-177: Consider avoidingtime.Sleepfor test synchronization.The
time.Sleep(10 * time.Millisecond)on line 160 is a fragile synchronization mechanism that could cause flaky tests on slower CI runners.🔎 Suggested improvement using channel synchronization
Consider adding a "ready" signal from the watcher's receive loop, or use a retry/poll pattern with shorter intervals:
// Alternative: poll until watcher is responsive deadline := time.Now().Add(100 * time.Millisecond) for time.Now().Before(deadline) { // The receive loop is running if we can read from done without blocking select { case <-time.After(time.Millisecond): default: } }Or expose a ready channel from the Watcher for tests to synchronize on.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
43-56: Consider wrapping errors and documenting unusedoptsparameter.Two observations:
- The
opts metav1.GetOptionsparameter is unused. If this is intentional (gRPC doesn't support these options), consider adding a brief comment or using_ metav1.GetOptionsto make this explicit.- Per coding guidelines, errors should be wrapped with context using
fmt.Errorf("context: %w", err). However, if preserving the original gRPC error type for status extraction is intentional, this is acceptable.🔎 Optional: Add error context
func (c *gpus) Get(ctx context.Context, name string, opts metav1.GetOptions) (*devicev1alpha1.GPU, error) { resp, err := c.client.GetGpu(ctx, &pb.GetGpuRequest{Name: name}) if err != nil { - return nil, err + return nil, fmt.Errorf("get GPU %q: %w", name, err) }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (48)
.coderabbit.yaml(1 hunks).gitignore(1 hunks).versions.yaml(1 hunks)Makefile(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (5)
- api/hack/boilerplate.go.txt
- client-go/hack/boilerplate.go.txt
- client-go/examples/controller-shim/README.md
- client-go/hack/boilerplate_overlay.go.txt
- client-go/examples/fake-server/README.md
🚧 Files skipped from review as they are similar to previous changes (17)
- client-go/version/version_test.go
- client-go/examples/streaming-daemon/README.md
- client-go/nvgrpc/client_conn.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
- .gitignore
- api/device/v1alpha1/gpu_conversion.go
- client-go/nvgrpc/options.go
- client-go/version/version.go
- client-go/nvgrpc/interceptors.go
- api/device/v1alpha1/converter.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
- client-go/README.md
- client-go/nvgrpc/options_test.go
- client-go/nvgrpc/client_conn_test.go
- client-go/nvgrpc/config.go
- client-go/hack/apply-overlays.sh
- api/device/v1alpha1/register.go
🧰 Additional context used
📓 Path-based instructions (3)
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
client-go/go.modapi/go.mod
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
api/device/v1alpha1/gpu_conversion_test.goapi/device/v1alpha1/doc.goclient-go/nvgrpc/config_test.goclient-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goapi/device/v1alpha1/gpu_types.goclient-go/nvgrpc/watcher.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/examples/basic-client/main.goclient-go/examples/controller-shim/main.goclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/examples/fake-server/main.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/interceptors_test.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
api/device/v1alpha1/gpu_conversion_test.goclient-go/nvgrpc/config_test.goclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/interceptors_test.go
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
client-go/go.modMakefileapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/go.modclient-go/examples/README.mdapi/Makefileclient-go/hack/overlays/client/versioned/clientset.goclient-go/examples/basic-client/main.goclient-go/examples/basic-client/README.md.versions.yamlclient-go/DEVELOPMENT.mdapi/go.modclient-go/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
client-go/go.modMakefileapi/Makefile.versions.yamlapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/go.modclient-go/nvgrpc/watcher.goclient-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.goapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/go.modclient-go/examples/README.mdclient-go/nvgrpc/watcher_test.goclient-go/examples/fake-server/main.goclient-go/hack/overlays/client/versioned/integration_test.go.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
Makefile.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
Makefileclient-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/nvgrpc/watcher.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
🧬 Code graph analysis (9)
api/device/v1alpha1/gpu_conversion_test.go (1)
api/device/v1alpha1/gpu_conversion.go (4)
FromProto(25-32)ToProto(35-40)FromProtoList(43-48)ToProtoList(51-56)
client-go/examples/streaming-daemon/main.go (6)
client-go/hack/overlays/client/versioned/clientset.go (2)
New(79-83)NewForConfigAndClient(48-65)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(58-63)NewForConfigAndClient(39-44)client-go/nvgrpc/config.go (3)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)Config(41-49)client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (6)
DeviceV1alpha1Interface(9-12)DeviceV1alpha1Client(15-18)NewForConfig(27-35)NewForConfigAndClient(39-44)NewForConfigOrDie(48-55)New(58-63)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (5)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
DeviceV1alpha1Client(15-18)api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
client-go/examples/fake-server/main.go (3)
client-go/nvgrpc/config.go (2)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/hack/overlays/client/versioned/integration_test.go (5)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
NewForConfigAndClient(39-44)New(58-63)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/interceptors_test.go (1)
client-go/nvgrpc/interceptors.go (2)
NewLatencyUnaryInterceptor(28-59)NewLatencyStreamInterceptor(62-92)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (53)
client-go/examples/basic-client/README.md (1)
1-38: ✅ Documentation looks good.The previous issue with the incorrect relative path (
../../fake-server) has been resolved. Both references on lines 12 and 27 now correctly point to../fake-server, which properly navigates from the basic-client directory to the fake-server example.The README is well-structured with clear sections on key concepts, running instructions for both privileged and unprivileged execution, and concrete expected output examples. This provides developers with a solid reference implementation for the NVIDIA Device API Go Client.
client-go/examples/streaming-daemon/main.go (7)
42-48: LGTM!The connection target resolution correctly uses the canonical constants from the nvgrpc package, addressing the previous review feedback.
50-61: LGTM!The custom interceptor implementations correctly demonstrate metadata injection for unary calls and lifecycle logging for stream calls. The inline definitions are appropriate for example code.
63-77: LGTM!The DialOptions configuration and gRPC connection setup correctly use the nvgrpc package patterns, with proper error handling and resource cleanup via defer.
79-85: LGTM!The clientset initialization correctly uses
NewForConfigAndClientwhich is appropriate when custom gRPC lifecycle or interceptor management is needed. The explanatory comment is helpful.
87-89: LGTM!Proper shutdown handling implementation using
signal.NotifyContextfor graceful termination on SIGINT or SIGTERM, as required by coding guidelines.
91-97: LGTM!The List call correctly demonstrates the unary interceptor trigger and handles errors appropriately for example code.
99-146: Watch implementation is correct, but consider the architectural pattern.The Watch stream and event processing logic is well-implemented with proper error handling, type assertions, and cleanup. However, the coding guidelines prefer informers over direct API calls for watching Kubernetes resources.
While this example intentionally demonstrates manual Watch usage to showcase the stream interceptor behavior, consider documenting in comments or README that production code should typically use Informers for better reliability and caching benefits.
Based on coding guidelines: "Prefer informers over direct API calls for watching Kubernetes resources."
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
1-12: LGTM! Clean adapter structure.The type definition is clear and appropriate for wrapping the gRPC stream into a Kubernetes-compatible event provider.
Makefile (1)
343-343: LGTM!The addition of the
hack/ignore pattern aligns well with the overlay-based code generation workflow introduced in this PR. This prevents license header checks from flagging custom overlay files that may have different header requirements or are meant to replace generated code.client-go/hack/overlays/client/versioned/clientset.go (1)
1-83: LGTM!This clientset implementation follows Kubernetes client-go conventions with proper nil checks, config shallow-copying to prevent mutation, and clean error propagation. The constructor patterns (NewForConfig, NewForConfigAndClient, NewForConfigOrDie, New) provide flexibility for different use cases.
.versions.yaml (1)
49-50: LGTM!The added tool versions are appropriate for the code generation workflow. The
kubernetes_code_genversion aligns with the Kubernetes v0.34 release family used by client-go dependencies, andgoverterv1.9.2 is the latest stable release.client-go/examples/README.md (1)
1-38: LGTM!This README provides clear, well-structured documentation for the example suite. The table-based overview effectively organizes examples by complexity, and the prerequisites section clearly explains the fake server requirement for local testing.
api/device/v1alpha1/doc.go (1)
1-19: LGTM!This package documentation follows Go conventions with a proper license header and Kubebuilder group annotation for code generation. The package-level doc comment clearly describes the API group's purpose.
api/device/v1alpha1/gpu_conversion_test.go (1)
1-153: LGTM!These conversion tests are comprehensive and well-structured. They properly validate nil handling, round-trip conversion integrity using
protocmp.Transform(), and specific field mappings like name lowercasing and ResourceVersion propagation. The use oftimestamppbfor time values and nested condition structures demonstrates thorough coverage.client-go/examples/basic-client/main.go (2)
30-47: LGTM!The setup logic correctly uses the library constants for target resolution and properly initializes the clientset with error handling. The structured logging via
stdraligns with coding guidelines.
49-82: LGTM!The GPU listing, fetching, and status inspection logic is well-structured. Good use of
meta.IsStatusConditionTruefor Kubernetes-style condition checks and meaningful variable naming (isReady).api/go.mod (1)
3-3: LGTM!The Go version bump to 1.25.5 and the addition of
go-cmpas a direct dependency along with the Kubernetes ecosystem indirect dependencies are appropriate for supporting the new API types and conversions.Also applies to: 6-6, 19-33
client-go/go.mod (2)
1-15: LGTM!The module declaration, Go version, replace directive for the local api module, and direct dependencies are properly configured. Kubernetes dependencies are consistently aligned at v0.34.1, and the controller-runtime version is compatible.
17-74: Indirect dependencies are appropriate.The transitive dependencies from Kubernetes client-go and controller-runtime are expected. Version alignment looks consistent across the K8s ecosystem modules.
api/proto/device/v1alpha1/gpu.proto (3)
27-51: LGTM on message structure!The
ObjectMetaandListMetamessages correctly implement the Kubernetes metadata pattern for optimistic concurrency. TheGpuandGpuListmessages follow the standard Kubernetes resource model (metadata/spec/status). Field documentation is comprehensive as required by coding guidelines.Also applies to: 61-78
80-117: Well-designed Condition message.The
Conditionmessage correctly follows the Kubernetes condition pattern with appropriate fields (type,status,last_transition_time,reason,message). The use ofgoogle.protobuf.Timestampforlast_transition_timeis appropriate.
152-167: LGTM on request messages!Adding
resource_versiontoListGpusRequestandWatchGpusRequestenables clients to list resources at a specific version and establish Watch streams from a consistent point, following Kubernetes API conventions.client-go/examples/controller-shim/main.go (1)
80-101: LGTM on NewInformer implementation!The
NewInformerfunction correctly returns the gRPC-backed informer for GPU objects and falls back to a standardSharedIndexInformerfor other types. The indexer merging logic properly handles conflicts by preferring existing implementations.client-go/nvgrpc/watcher_test.go (4)
31-58: LGTM! Well-structured test for normal event flow.The test correctly validates the watcher's handling of ADDED, MODIFIED, and DELETED events in sequence. Good use of channel-based event injection.
60-83: Good coverage for unknown event type handling.Verifies that unknown event types are silently skipped while subsequent valid events are still processed correctly.
85-118: Well-designed table-driven test for error scenarios.Good use of table-driven testing pattern as per coding guidelines. The test cases cover important gRPC error code mappings (Internal, OutOfRange, InvalidArgument) and verify the correct translation to Kubernetes
metav1.Status.
179-239: Test utilities are well-designed and correctly implement the Source interface.
FakeObjectproperly implementsruntime.ObjectviaDeepCopyObject(), andFakeSourcecorrectly handles the event/error injection patterns needed for testing. TheClose()method properly handles the double-close case.api/device/v1alpha1/gpu_types.go (1)
21-70: LGTM! Well-structured Kubernetes API types.The type definitions follow Kubernetes API conventions correctly:
- Proper use of
metav1.TypeMetaandmetav1.ObjectMetaembedding- Appropriate codegen markers for client generation (
+genclient,+genclient:nonNamespaced,+genclient:onlyVerbs)- Correct
+k8s:deepcopy-gen:interfacesmarker forruntime.Objectimplementation- Good documentation on the UUID format in
GPUSpecclient-go/nvgrpc/watcher.go (5)
32-46: Well-designed Source interface and Watcher struct.The
Sourceinterface provides a clean abstraction for event sources, and theWatcherstruct correctly usessync.Oncefor idempotent shutdown as addressed from previous review feedback.
48-64: LGTM! Constructor properly initializes and starts the receive loop.The buffered channel (size 100) provides reasonable backpressure handling, and the background goroutine is correctly started.
66-81: Clean idempotent Stop implementation.Good use of
sync.Onceto ensure safe concurrent calls toStop(). The logging at V(4) level is appropriate for operational debugging.
83-136: Solid receive loop implementation with proper shutdown handling.The implementation correctly:
- Defers both cleanup (
close(w.result)) andStop()to ensure resources are released- Handles
io.EOFandcodes.Canceledas normal stream closure- Maps event types appropriately and skips unknown types
- Checks
w.donebefore sending to prevent blocking on a stopped watcher
138-170: Good gRPC-to-Kubernetes error code mapping.The
sendErrorfunction correctly maps gRPC status codes to Kubernetesmetav1.Statusreasons. The mapping ofOutOfRange,ResourceExhausted, andInvalidArgumentto HTTP 410 (Expired) is important for triggering Informer re-list behavior.api/Makefile (6)
19-41: LGTM! Well-organized variable definitions.The string manipulation helpers and API package variables are correctly defined. The
API_PKGS_COMMAvariable (line 37) properly addresses the previously flagged missing variable issue.Minor: Line 36 is missing a space after
#in the comment for consistency.
55-59: Good fallback for GO_VERSION resolution.Properly attempts to read from
go.modfirst, then falls back togo env GOVERSION. This ensures consistent toolchain behavior across environments.
96-109: LGTM! Code generation workflow is well-structured.The
code-gentarget correctly orchestrates tool installation and all generation steps, followed bygo mod tidyto synchronize dependencies.
111-125: Proto generation loop is correct.The
$(foreach)loop properly iterates overAPI_VERSIONSand generates protobuf bindings for each version with appropriateprotocflags.
127-141: Code generation targets are well-defined.Both
deepcopy-genandconversion-gentargets correctly use the package variables and iterate over versions as needed.
190-205: LGTM! go-install-tool macro with GOTOOLCHAIN.The macro correctly uses
GOTOOLCHAIN=$(GO_VERSION)to ensure tools are installed with the expected Go version, and implements version-specific binary caching with symlinks.client-go/examples/fake-server/main.go (5)
42-91: LGTM! Well-structured server initialization and graceful shutdown.The main function correctly:
- Resolves the socket path from environment or default
- Creates the socket directory and cleans stale sockets
- Sets up signal handling for graceful shutdown
- Cleans up the socket file on exit
93-128: Good fake server initialization with realistic GPU state.The
newFakeServerproperly initializes 8 GPUs with unique UUIDs and initial Ready conditions. The structure mirrors the actual API types well.
130-175: Simulation and broadcast logic is appropriate for a fake server.The
simulateChangesgoroutine properly increments resource versions and toggles conditions. The non-blocking send inbroadcast()is acceptable for a test server to avoid blocking on slow consumers.
205-255: WatchGpus implementation follows correct streaming patterns.The implementation correctly:
- Sends initial ADDED events for all GPUs
- Registers for updates via a listener channel
- Cleans up the listener on disconnect via defer
- Handles context cancellation gracefully
257-263: UUID generation is acceptable for a fake server.Using
math/randinstead ofcrypto/randis fine for this test utility. The UUID format follows the GPU-prefixed pattern documented inGPUSpec.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (4)
1-13: LGTM on imports and package declaration.The imports are appropriately organized with standard library, internal packages, and external dependencies. The import alias for
contextis redundant but harmless.
58-71: OnlyResourceVersionis used fromListOptions.The method only passes
opts.ResourceVersionto the gRPC request, ignoring otherListOptionsfields likeLabelSelector,FieldSelector,Limit, andContinue. This is likely intentional given the gRPC API design, but consider documenting which options are supported to set caller expectations.
35-41: No issues found. TheClientConn()method is properly implemented onDeviceV1alpha1Clientand correctly called in thenewGPUsconstructor.
73-87: Context cancellation andgpuStreamAdapterimplementation verified.The Watch method correctly implements context cleanup:
cancel()is called on error before returning, and the cancellation function is passed tonvgrpc.NewWatcherfor cleanup during normal shutdown. ThegpuStreamAdapterstruct implements thenvgrpc.Sourceinterface with both required methods—Next()returns(string, runtime.Object, error)andClose()returnserror—matching the interface definition innvgrpc/watcher.go.client-go/Makefile (4)
54-67: Well-structured shell and Go version configuration.Good practices:
- Shell configured with
pipefailfor proper error propagation- GO_VERSION extraction with fallback to
go env GOVERSIONhandles both go.mod toolchain directive and environments without it
74-79: Good fail-fast behavior with helpful error message.The yq dependency check provides clear installation instructions for developers, which is a good UX practice for required build tools.
100-114: Targets are well-structured with appropriate code exclusions.The
buildandtesttargets correctly exclude overlay templates and examples from compilation/testing since overlays are templates and examples may have different build requirements.
198-213: Well-designed tool installation macro.The
go-install-toolmacro implements a solid pattern:
- Version-specific binary naming (
$(1)-$(3)) prevents conflicts- Symlinks allow seamless version switching
GOTOOLCHAIN=$(GO_VERSION)ensures consistent Go version during installation- Skips download if versioned binary already exists
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
♻️ Duplicate comments (9)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-11: Missing package-level godoc.This issue was previously flagged. The coding guidelines require package-level documentation for all Go packages.
As per coding guidelines.
13-15: Missing function comment for exported method.This issue was previously flagged. The coding guidelines require function comments for all exported Go functions.
As per coding guidelines.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
37-44: Validate the config in NewForConfigAndClient.This issue was previously flagged. The function accepts a config but doesn't validate it, potentially allowing invalid configurations to propagate.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
25-27: CloseSend() is not appropriate for server-streaming RPCs.This issue was previously flagged. For server-streaming RPCs like WatchGpus, the client only receives messages. Calling CloseSend() is incorrect and should either return nil directly or rely on context cancellation.
client-go/examples/streaming-daemon/main.go (1)
146-148: Fix misleading log message.This issue was previously flagged. The log message says "context timeout reached" but the context is created with
signal.NotifyContext(line 93) and cancels on OS signals, not on timeout.api/proto/device/v1alpha1/gpu.proto (1)
35-37: Inconsistent indentation in comment block.Lines 35-37 use tab characters while surrounding lines use spaces. This creates inconsistent formatting.
🔎 Proposed fix
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorffrom a goroutine is unsafe and can cause race conditions or panics if the test completes before the goroutine executes. Sincec.Startblocks until context cancellation and errors typically only occur on shutdown, consider logging the error instead or using an error channel.🔎 Suggested fix using error channel
+ errCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + errCh <- err } + close(errCh) }()client-go/examples/fake-server/main.go (1)
199-207:ListMetais not populated in the response.The
GpuListresponse doesn't includemetadata.resource_version, which is needed for clients to establish a watch from a consistent point (List-then-Watch pattern). Consider tracking a global version and populating it.🔎 Suggested fix
gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: "1", // Or track a global version + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), }client-go/Makefile (1)
187-187: Declare thetoolstarget as.PHONY.The
toolstarget doesn't produce a file and should be declared.PHONYto ensure it always runs when invoked.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)
🧹 Nitpick comments (7)
client-go/nvgrpc/options_test.go (1)
48-64: Use testify assertions for better test readability.The test assertions currently use plain
t.Errorf, but the coding guidelines specify usingtestify/assertandtestify/requirefor Go tests. This improves readability and provides clearer failure messages.As per coding guidelines.
🔎 Suggested refactor using testify
+import ( + "github.com/stretchr/testify/assert" +) + t.Run("Logger is correctly assigned", func(t *testing.T) { - if dOpts.logger != testLogger { - t.Errorf("expected logger to be set, got %v", dOpts.logger) - } + assert.Equal(t, testLogger, dOpts.logger, "logger should be correctly assigned") }) t.Run("Unary interceptors are correctly appended", func(t *testing.T) { - if len(dOpts.unaryInterceptors) != 2 { - t.Errorf("expected 2 unary interceptors, got %d", len(dOpts.unaryInterceptors)) - } + assert.Len(t, dOpts.unaryInterceptors, 2, "should have 2 unary interceptors") }) t.Run("Stream interceptors are correctly appended", func(t *testing.T) { - if len(dOpts.streamInterceptors) != 2 { - t.Errorf("expected 2 stream interceptors, got %d", len(dOpts.streamInterceptors)) - } + assert.Len(t, dOpts.streamInterceptors, 2, "should have 2 stream interceptors") })client-go/nvgrpc/watcher_test.go (2)
31-33: Optional: Unused context variable in some tests.In
TestWatcher_NormalEvents,TestWatcher_UnknownEventType_Ignored,TestWatcher_Errorssubtests, andTestWatcher_ErrorTerminatesStream, thectxvariable fromcontext.WithCancel()is created but never used directly (only thecancelfunction is used). Consider using_instead:_, cancel := context.WithCancel(context.Background())Note:
TestWatcher_Stopcorrectly usesctxto verify cancellation, so no change needed there.Also applies to: 60-62, 97-100, 120-122
197-239: Optional: Document thread-safety limitations ofFakeSource.The
FakeSourceimplementation is not thread-safe (particularly theerrsslice manipulation in lines 212-216). While this is acceptable since the watcher callsNext()from a single goroutine (go w.receive()), consider adding a comment documenting this limitation to prevent misuse in future tests.🔎 Suggested documentation
-// FakeSource implements nvgrpc.Source. +// FakeSource implements nvgrpc.Source for testing. +// Note: FakeSource is not thread-safe and should only be used +// with sequential calls to Next() from a single goroutine. type FakeSource struct { events chan testEvent errs []error done chan struct{} }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
20-22: Add function comment for exported method.The coding guidelines require function comments for all exported Go functions. Add a comment describing what GPUs() returns.
As per coding guidelines.
🔎 Suggested documentation
+// GPUs returns a GPUInterface for interacting with GPU resources +// in the device.nvidia.com v1alpha1 API group. func (c *DeviceV1alpha1Client) GPUs() GPUInterface { return newGPUs(c) }client-go/hack/overlays/client/versioned/clientset.go (1)
1-1: Add package-level documentation.Per coding guidelines, package-level godoc is required. Add a package comment describing the purpose of this overlay clientset.
🔎 Proposed fix
+// Package versioned provides a versioned clientset for the NVIDIA Device API. +// It wraps the generated client code with gRPC transport configuration, +// enabling communication over Unix Domain Sockets. package versionedapi/Makefile (2)
111-125: Protobuf generation loop is functional but could be more robust.The
$(foreach)loop will continue even if protoc fails for one version. Consider adding explicit error handling or using a shell loop with proper exit codes for multi-version generation.
36-37: Minor: Missing space after#in comment.For consistency with other comments in the file, add a space after
#.🔎 Proposed fix
-#Helper for tools that need comma-separated package paths +# Helper for tools that need comma-separated package paths API_PKGS_COMMA := $(subst $(SPACE),$(COMMA),$(API_PKGS))
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (48)
.coderabbit.yaml(1 hunks).gitignore(1 hunks).versions.yaml(1 hunks)Makefile(1 hunks)api/Makefile(5 hunks)api/device/v1alpha1/converter.go(1 hunks)api/device/v1alpha1/doc.go(1 hunks)api/device/v1alpha1/gpu_conversion.go(1 hunks)api/device/v1alpha1/gpu_conversion_test.go(1 hunks)api/device/v1alpha1/gpu_types.go(1 hunks)api/device/v1alpha1/register.go(1 hunks)api/go.mod(2 hunks)api/hack/boilerplate.go.txt(1 hunks)api/proto/device/v1alpha1/gpu.proto(4 hunks)client-go/DEVELOPMENT.md(1 hunks)client-go/Makefile(1 hunks)client-go/README.md(1 hunks)client-go/examples/README.md(1 hunks)client-go/examples/basic-client/README.md(1 hunks)client-go/examples/basic-client/main.go(1 hunks)client-go/examples/controller-shim/README.md(1 hunks)client-go/examples/controller-shim/main.go(1 hunks)client-go/examples/fake-server/README.md(1 hunks)client-go/examples/fake-server/main.go(1 hunks)client-go/examples/streaming-daemon/README.md(1 hunks)client-go/examples/streaming-daemon/main.go(1 hunks)client-go/go.mod(1 hunks)client-go/hack/apply-overlays.sh(1 hunks)client-go/hack/boilerplate.go.txt(1 hunks)client-go/hack/boilerplate_overlay.go.txt(1 hunks)client-go/hack/overlays/client/versioned/clientset.go(1 hunks)client-go/hack/overlays/client/versioned/integration_test.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go(1 hunks)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go(1 hunks)client-go/nvgrpc/client_conn.go(1 hunks)client-go/nvgrpc/client_conn_test.go(1 hunks)client-go/nvgrpc/config.go(1 hunks)client-go/nvgrpc/config_test.go(1 hunks)client-go/nvgrpc/interceptors.go(1 hunks)client-go/nvgrpc/interceptors_test.go(1 hunks)client-go/nvgrpc/options.go(1 hunks)client-go/nvgrpc/options_test.go(1 hunks)client-go/nvgrpc/watcher.go(1 hunks)client-go/nvgrpc/watcher_test.go(1 hunks)client-go/version/version.go(1 hunks)client-go/version/version_test.go(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- client-go/examples/streaming-daemon/README.md
- client-go/hack/boilerplate_overlay.go.txt
- client-go/examples/README.md
- api/hack/boilerplate.go.txt
🚧 Files skipped from review as they are similar to previous changes (23)
- client-go/version/version_test.go
- client-go/examples/basic-client/main.go
- client-go/go.mod
- .coderabbit.yaml
- api/device/v1alpha1/doc.go
- client-go/examples/controller-shim/main.go
- client-go/examples/fake-server/README.md
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
- client-go/nvgrpc/interceptors_test.go
- api/device/v1alpha1/gpu_types.go
- client-go/nvgrpc/config.go
- client-go/nvgrpc/watcher.go
- api/device/v1alpha1/register.go
- client-go/nvgrpc/interceptors.go
- client-go/nvgrpc/client_conn.go
- client-go/nvgrpc/client_conn_test.go
- client-go/nvgrpc/config_test.go
- client-go/version/version.go
- api/go.mod
- client-go/examples/controller-shim/README.md
- client-go/hack/boilerplate.go.txt
- Makefile
- client-go/README.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/examples/streaming-daemon/main.goapi/device/v1alpha1/gpu_conversion.goclient-go/examples/fake-server/main.goclient-go/nvgrpc/options.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goapi/device/v1alpha1/converter.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/options_test.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/integration_test.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/options_test.goapi/device/v1alpha1/gpu_conversion_test.goclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/integration_test.go
🧠 Learnings (16)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/examples/streaming-daemon/main.goclient-go/examples/fake-server/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
.gitignoreclient-go/examples/basic-client/README.md.versions.yamlclient-go/hack/apply-overlays.shclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goapi/Makefileclient-go/DEVELOPMENT.mdclient-go/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.gitignore.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
.gitignore.versions.yamlclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/nvgrpc/watcher_test.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
.versions.yamlapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/examples/fake-server/main.goclient-go/nvgrpc/options.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/nvgrpc/options.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
api/device/v1alpha1/gpu_conversion_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.go
🧬 Code graph analysis (9)
api/device/v1alpha1/gpu_conversion.go (2)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/examples/fake-server/main.go (3)
client-go/nvgrpc/config.go (2)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
api/device/v1alpha1/gpu_conversion_test.go (1)
api/device/v1alpha1/gpu_conversion.go (4)
FromProto(25-32)ToProto(35-40)FromProtoList(43-48)ToProtoList(51-56)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
client-go/hack/overlays/client/versioned/integration_test.go (4)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
⏰ 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). (23)
- GitHub Check: ko-build-test (health-monitors/csp-health-monitor, ./cmd/maintenance-notifier)
- GitHub Check: ko-build-test (janitor, .)
- GitHub Check: container-build-test (gpu-health-monitor-dcgm3, make -C health-monitors/gpu-health-monitor docker...
- GitHub Check: container-build-test (gpu-health-monitor-dcgm4, make -C health-monitors/gpu-health-monitor docker...
- GitHub Check: container-build-test (file-server-cleanup, make -C log-collector docker-build-file-server-cleanup)
- GitHub Check: container-build-test (syslog-health-monitor, make -C health-monitors/syslog-health-monitor docker...
- GitHub Check: container-build-test (log-collector, make -C log-collector docker-build-log-collector)
- GitHub Check: E2E Tests (ARM64 + MongoDB)
- GitHub Check: E2E Tests (AMD64 + PostgreSQL)
- GitHub Check: E2E Tests (AMD64 + MongoDB)
- GitHub Check: E2E Tests (ARM64 + PostgreSQL)
- GitHub Check: CodeQL PR Analysis
- GitHub Check: modules-lint-test (fault-quarantine)
- GitHub Check: modules-lint-test (labeler)
- GitHub Check: modules-lint-test (node-drainer)
- GitHub Check: modules-lint-test (platform-connectors)
- GitHub Check: modules-lint-test (fault-remediation)
- GitHub Check: modules-lint-test (health-events-analyzer)
- GitHub Check: modules-lint-test (janitor)
- GitHub Check: modules-lint-test (store-client)
- GitHub Check: health-monitors-lint-test (kubernetes-object-monitor)
- GitHub Check: health-monitors-lint-test (csp-health-monitor)
- GitHub Check: health-monitors-lint-test (syslog-health-monitor)
🔇 Additional comments (37)
.gitignore (1)
18-18: LGTM!The addition correctly mirrors the existing
api/bin/*pattern and aligns with the new client-go module's code-generation artifacts. Placement in the Go section is appropriate.client-go/DEVELOPMENT.md (1)
1-104: Well-structured development guide.This documentation provides clear, actionable guidance on the code-generation workflow, overlay pattern, and project directory structure. The use of bash examples, a mermaid diagram, and callouts (TIP, WARNING) makes it accessible to developers unfamiliar with the SDK. The documentation aligns well with the PR objectives and supports the maintainability of the client-go module.
client-go/nvgrpc/options.go (1)
22-50: LGTM! Functional options pattern correctly implemented.The code properly implements the functional options pattern for gRPC client configuration:
- All exported types and functions have appropriate godoc comments (as per coding guidelines)
- Interceptor functions correctly append to slices, supporting multiple interceptors
- Logger configuration is straightforward and correct
- The pattern integrates well with the ClientConnFor usage shown in the context
.versions.yaml (1)
49-50: LGTM!The tool versions are appropriate. Goverter v1.9.2 is the latest release, and kubernetes_code_gen v0.34.1 matches the client-go version in use, ensuring compatibility within the same Kubernetes release family.
client-go/hack/apply-overlays.sh (1)
1-29: LGTM!The script has proper error handling with
set -euo pipefail, validates prerequisites (boilerplate file and repository root), and correctly applies overlays by concatenating boilerplate with source files.api/device/v1alpha1/gpu_conversion_test.go (1)
30-153: LGTM!The tests comprehensively cover nil handling and round-trip conversions for both GPU and GPUList types. The use of
protocmp.Transform()for protobuf comparison is the correct approach, and the tests validate critical fields like name lowercasing and ResourceVersion propagation.api/device/v1alpha1/gpu_conversion.go (1)
15-56: LGTM!The conversion helpers are well-implemented with proper nil checks, clear godoc comments, and consistent delegation to the converter singleton. The build tag
!goverterappropriately guards against conflicts with generated code.client-go/examples/streaming-daemon/main.go (1)
15-145: LGTM!The example demonstrates proper gRPC client setup with custom interceptors, signal-based shutdown handling, and both unary (List) and streaming (Watch) operations. The package documentation is clear and the code follows best practices for context management and error handling.
api/proto/device/v1alpha1/gpu.proto (2)
27-51: Good Kubernetes-native metadata design.The
ObjectMetaandListMetamessages properly mirror Kubernetes API machinery patterns withresource_versionfor optimistic concurrency control. TheGpuandGpuListstructures correctly embed these metadata types.Also applies to: 61-78
152-167: Correct implementation of resource versioning for List/Watch.Adding
resource_versionto bothListGpusRequestandWatchGpusRequestenables the List-then-Watch pattern, allowing clients to establish watches from a consistent point in time. This aligns with Kubernetes API conventions.client-go/hack/overlays/client/versioned/integration_test.go (4)
33-62: Well-structured test setup with proper resource cleanup.The test setup correctly uses
bufconnfor in-process gRPC testing, establishes a context with timeout, and properly defers cleanup withs.Stop()andconn.Close(). This follows good testing patterns.
64-129: Comprehensive Get/List/Watch flow testing.The subtests properly validate the core client operations with appropriate timeout handling. The Watch test correctly verifies both initial snapshot (ADDED event) and live updates (MODIFIED event).
131-182: Proper informer lifecycle management.The test correctly instantiates the informer before starting the factory, uses
cache.WaitForCacheSyncfor synchronization, and employswait.PollUntilContextTimeoutfor verifying asynchronous cache updates.
256-336: Thread-safe mock server with proper watch semantics.The mock server correctly implements thread-safe access with
sync.RWMutex, sends an initial snapshot of ADDED events, and properly handles context cancellation in the watch stream. The buffered channel prevents blocking during event dispatch.client-go/examples/fake-server/main.go (6)
15-20: Package documentation present as required.The package-level godoc properly documents the fake server's purpose and behavior.
47-96: Proper server lifecycle management with graceful shutdown.The main function correctly handles socket setup, stale socket cleanup, and graceful shutdown via signal handling. Using
nvgrpc.NvidiaDeviceAPITargetEnvVarandnvgrpc.DefaultNvidiaDeviceAPISocketconstants ensures consistency with the client SDK.
98-133: Clean separation of internal types from protobuf wire format.Using
devicev1alpha1.GPUinternally and converting to protobuf at the API boundary is the correct pattern. The initialization properly sets up GPU conditions with meaningful defaults.
137-180: Correct simulation with non-blocking broadcast.The
simulateChangesfunction properly incrementsResourceVersionfor watch semantics, usesDeepCopyto prevent data races, and the non-blocking broadcast pattern prevents slow consumers from blocking the simulation loop.
210-260: Correct watch stream implementation with proper lifecycle management.The
WatchGpusmethod correctly sends an initial snapshot of ADDED events, registers for updates, handles context cancellation, and cleans up the listener on exit. The anonymous function pattern for the initial snapshot ensures proper lock scope.
262-268: UUID generation is acceptable for this fake server context.While
math/randis not cryptographically secure, it's appropriate for a local testing fake server. The UUID version 4 bit manipulation is correct.client-go/hack/overlays/client/versioned/clientset.go (2)
12-24: Clean interface design following client-go patterns.The
InterfaceandClientsetstruct properly follow Kubernetes client-go conventions, enabling easy mocking and dependency injection.
26-83: Well-designed constructor variants with proper validation.The constructors follow established client-go patterns:
- Defensive nil checks prevent runtime errors
- Config shallow-copying prevents external mutation
NewForConfigOrDiepattern is idiomatic for startup codeNewprovides a simple escape hatch for pre-configured connectionsapi/device/v1alpha1/converter.go (2)
23-104: Well-designed bidirectional converter interface with goverter annotations.The
Converterinterface properly defines bidirectional conversion between protobuf and Kubernetes types. The goverter annotations correctly:
- Map field name differences (e.g.,
Uuid↔UUID,Metadata↔ObjectMeta)- Ignore Kubernetes-specific fields not present in protobuf (e.g.,
Namespace,GenerateName)- Ignore protobuf internal fields (
state,sizeCache,unknownFields)
106-133: Correct TypeMeta and Timestamp conversion helpers.The
FromProtobufTypeMetaandFromProtobufListTypeMetafunctions now correctly useSchemeGroupVersion.String()to produce the fullgroup/versionformat (device.nvidia.com/v1alpha1). The timestamp conversion properly handles nil values.client-go/Makefile (7)
1-14: License header looks good.Standard Apache 2.0 license header is correctly applied.
19-47: Configuration variables are well-structured.The string manipulation helpers and module/version configuration follow standard Makefile patterns. The LDFLAGS construction with version injection is correct.
54-67: Shell and Go version setup is correct.The bash pipefail setup and Go version extraction with fallback are well-implemented.
74-84: Tool version management is well-implemented.The centralized version file approach with yq parsing ensures consistent tooling across the project. The early failure on missing yq is helpful for developer experience.
100-104: Code generation workflow is correctly structured.The dependency chain ensures tools are installed first, then client code is generated, overlays are applied, and finally listers/informers are generated. Running
go mod tidyat the end properly synchronizes dependencies.
198-213: Tool installation macro is well-designed.The versioned binary approach with symlinks is a robust pattern that handles upgrades gracefully and allows version coexistence. Using
GOTOOLCHAINensures consistent Go toolchain usage.
110-113: Grep exclusion patterns work correctly; inconsistency is harmless.The pattern inconsistency noted (
/listers/vsinformers/without leading slash) does not cause incorrect filtering because there are nolisters/orinformers/directories in this repository. The exclusions for/examples/and/hack/overlays/function as intended. If consistency is desired for maintainability, both patterns could use leading slashes:/listers/|/informers/— but this is not a functional issue.api/Makefile (6)
19-40: Configuration section is well-structured.The string manipulation helpers and API version configuration follow the same patterns as client-go/Makefile. The
API_PKGS_COMMAdefinition addresses the previously flagged issue.
76-79: Version management from central YAML file is a good practice.This ensures consistent tooling versions across the project.
136-141: Conversion generation target is correctly implemented.The typo with the double period appears to have been addressed. The per-version loop with goverter is appropriate.
143-167: Clean targets are comprehensive and well-organized.Using
findfor generated file cleanup is a safe approach that handles files in subdirectories correctly.
171-188: Tool installation targets are correctly implemented.The installation pattern is consistent across both Makefiles and uses the centralized version management properly.
194-205: GOTOOLCHAIN addition improves build reproducibility.Pinning the Go toolchain version during tool installation ensures consistent behavior across different environments.
client-go/DEVELOPMENT.md
Outdated
| # Downloads codegen tools, generates clients/listers/informers, and applies overlays | ||
| make code-gen | ||
| ``` | ||
| **Note**: This process runs `hack/apply-overlays.sh` to inject custom gRPC logic into the generated files. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of overlays, do we have other modes of extensions that are possible? Can we call the codegen tools as a library perhaps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call out. Using overlays is definitely not the most ideal. Gonna try out a couple ideas and see what might work better here.
| **Example**: To customize `client/versioned/clientset.go`, you must edit `hack/overlays/client/versioned/clientset.go`. | ||
|
|
||
| > [!WARNING] | ||
| > **Do not edit generated files directly.** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a CI check to ensure the files aren't manually edited by the user?
4f3e806 to
a1fae68
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (20)
client-go/version/version.go (1)
15-15: Add package-level godoc comment.The coding guidelines require package-level godoc for all Go packages. This issue was previously flagged but remains unaddressed.
As per coding guidelines, package-level godoc is required for all Go packages.
🔎 Suggested addition
+// Package version provides build-time version information and user-agent +// string generation for the nvidia-device-api-client. package versionclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-11: Add package-level godoc comment.The coding guidelines require package-level documentation for all Go packages. This was already flagged in a previous review.
As per coding guidelines.
13-15: Add function comment for exported method.The coding guidelines require function comments for all exported Go functions. This was already flagged in a previous review.
As per coding guidelines.
client-go/nvgrpc/watcher_test.go (5)
31-58: Test logic is sound; testify assertions already flagged.The test correctly validates normal event flow (ADDED, MODIFIED, DELETED) by pre-populating a buffered channel, consuming from ResultChan, and verifying event types. The use of stdlib testing methods (
t.Fatalf,t.Errorf) instead oftestify/assertandtestify/requirehas already been flagged in a previous review comment.
60-83: Good edge case coverage; testify assertions already flagged.The test correctly verifies that unknown event types are ignored and subsequent valid events are processed. The testify assertion issue has already been covered in a previous review comment.
85-118: Excellent table-driven structure; testify assertions already flagged.The test properly uses table-driven design to validate error mapping to Kubernetes
metav1.Statuswith appropriate reason and HTTP codes. The coverage of Internal (500), OutOfRange (410/Expired), and InvalidArgument (410/Expired) scenarios is thorough. The testify assertion issue has already been flagged in a previous review comment.
120-152: Correct termination behavior validation; testify assertions already flagged.The test correctly verifies that the first error terminates the stream and subsequent errors are not delivered. The use of a labeled break (
break Receive) is idiomatic for exiting the nested select/for structure. The testify assertion issue has already been flagged in a previous review comment.
154-177: Stop behavior test intent is valid; race condition and testify assertions already flagged.The test correctly validates that
Stop()cancels the context and closesResultChan. However, thetime.Sleepon line 160 introduces a race condition, and the use of stdlib testing methods instead of testify assertions—both issues have been comprehensively addressed in previous review comments.client-go/examples/controller-shim/main.go (3)
65-69: The informer factory is never started.The comment on line 67 states the Manager will start the injected informer, but controller-runtime only starts informers it creates through its own cache machinery. The gRPC-backed informer from
factoryneeds to be started explicitly; otherwise, factory-level coordination, proper cache sync, and shutdown may not work correctly.🔎 Suggested fix
Start the factory using the manager's context before starting the manager:
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + ctx := ctrl.SetupSignalHandler() + go factory.Start(ctx.Done()) + + // Wait for the informer cache to sync before proceeding + if !toolscache.WaitForCacheSync(ctx.Done(), gpuInformer.HasSynced) { + setupLog.Error(nil, "failed to sync informer cache") + os.Exit(1) + } + // Initialize the controller-runtime Manager.Then remove the duplicate
ctx := ctrl.SetupSignalHandler()from line 121.
135-146: Add godoc comment for exportedReconcilemethod.The exported
Reconcilemethod lacks documentation. Coding guidelines require function comments for all exported Go functions, starting with the function name.🔎 Suggested addition
+// Reconcile retrieves the requested GPU resource from the gRPC-backed cache +// and logs its name and UUID. It returns without error if the GPU is not found. func (r *GPUReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {As per coding guidelines, function comments are required for all exported Go functions.
148-152: Add godoc comment for exportedSetupWithManagermethod.The exported
SetupWithManagermethod lacks documentation. Coding guidelines require function comments for all exported Go functions, starting with the function name.🔎 Suggested addition
+// SetupWithManager registers this reconciler with the provided manager, +// configuring it to watch GPU resources. func (r *GPUReconciler) SetupWithManager(mgr ctrl.Manager) error {As per coding guidelines, function comments are required for all exported Go functions.
client-go/examples/basic-client/README.md (1)
20-38: Socket path mismatch persists between instructions and expected output.The environment variable at line 24 sets
unix:///tmp/device-api.sock, but the expected output at line 31 showsunix:///tmp/nvidia-device-api.sock. This inconsistency will confuse users trying to reproduce the example.🔎 Proposed fix
-"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///tmp/nvidia-device-api.sock" +"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///tmp/device-api.sock"api/proto/device/v1alpha1/gpu.proto (1)
32-38: Inconsistent indentation persists in ObjectMeta comments.Lines 35-37 use tabs while surrounding lines use spaces, creating formatting inconsistency.
🔎 Proposed fix
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/DEVELOPMENT.md (2)
10-11: Fix nested list indentation for markdown lint compliance.The nested list items use 4-space indentation instead of the expected 2 spaces.
🔎 Proposed fix
- * *macOS*: `brew install yq` - * *Linux*: See [yq installation](https://github.com/mikefarah/yq) + * *macOS*: `brew install yq` + * *Linux*: See [yq installation](https://github.com/mikefarah/yq)
77-77: Remove redundant phrase.The phrase "inside of" is redundant; use "inside" for conciseness.
🔎 Proposed fix
-The directory structure inside of `hack/overlays/` **must exactly mirror** the structure of the generated code. +The directory structure inside `hack/overlays/` **must exactly mirror** the structure of the generated code.client-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorf(or anytmethod) from a goroutine is unsafe and can cause race conditions or panics if the test completes before the goroutine executes. Sincec.Startblocks until context cancellation and typically only returns errors on shutdown, consider using an error channel or simply logging the error.🔎 Suggested fix using error channel
+ errCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + errCh <- err } + close(errCh) }()Then after the test logic completes, check for errors:
select { case err := <-errCh: if err != nil { t.Errorf("Cache failed to start: %v", err) } default: }client-go/examples/fake-server/main.go (1)
195-208:ListMeta.ResourceVersionis not populated in the response.The
GpuListresponse doesn't includeMetadata.ResourceVersion, which clients need for the List-then-Watch pattern to establish a watch from a consistent point. Consider tracking a global resource version or deriving it from the highest GPU resource version.🔎 Suggested fix
func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { s.mu.RLock() defer s.mu.RUnlock() + // Derive list resource version from the highest GPU resource version + var maxRV int + for _, gpu := range s.gpus { + rv, _ := strconv.Atoi(gpu.ResourceVersion) + if rv > maxRV { + maxRV = rv + } + } + gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: strconv.Itoa(maxRV), + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
37-44: Add defensive checks for config parameter.The function doesn't validate the config parameter, which could lead to panics or invalid client state:
- No nil check before calling
c.GetLogger()- No validation of config contents
🔎 Proposed fix
func NewForConfigAndClient(c *nvgrpc.Config, conn grpc.ClientConnInterface) (*DeviceV1alpha1Client, error) { + if c == nil { + return nil, fmt.Errorf("config cannot be nil") + } + if err := c.Validate(); err != nil { + return nil, err + } return &DeviceV1alpha1Client{ conn: conn, logger: c.GetLogger().WithName("device.v1alpha1"), }, nil }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
21-27: Define the missing GPUExpansion interface.The GPUInterface embeds
GPUExpansion(line 26), but this interface is not defined, which will cause a compilation failure. Following Kubernetes client-go patterns, create a new filegpu_expansion.goin the same directory:package v1alpha1 // GPUExpansion allows for extension of GPU interface type GPUExpansion interface{}This empty interface serves as an extension point for future methods.
client-go/Makefile (1)
187-187: Declare the tools target as PHONY.The
toolstarget should be declared.PHONYsince it doesn't produce a file output and is used as a convenience alias for tool binaries. Without this declaration, Make may incorrectly skip rebuilding if a file named "tools" exists.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)
🧹 Nitpick comments (6)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
21-23: Consider returningnildirectly instead of typed nil.The current implementation declares a typed
*grpc.ClientConnvariable and returns it, which creates a non-nil interface containing a nil pointer. This pattern can be confusing because interface nil checks (conn != nil) will pass, but any method call will panic.For clarity, return
nildirectly:🔎 Clearer nil return
func (c *FakeDeviceV1alpha1) ClientConn() grpc.ClientConnInterface { - var ret *grpc.ClientConn - return ret + return nil }client-go/nvgrpc/options_test.go (1)
25-46: Add test case for default logger behavior.The AI summary states this test "Verifies that a discard logger is correctly assigned when none is provided," but no such test case exists in the code. Consider adding a test case that verifies the default logger behavior when
WithLoggeris not called.🔎 Add test case for default logger
t.Run("Default logger is assigned when none provided", func(t *testing.T) { defaultOpts := &dialOptions{} // Apply options without WithLogger for _, opt := range []DialOption{ WithUnaryInterceptor(dummyUnary), } { opt(defaultOpts) } // Verify default logger is set (implementation-dependent check) if defaultOpts.logger.GetSink() == nil { t.Errorf("expected default logger to be initialized") } })Note: You may need to verify how the default logger is initialized in the actual implementation to write an accurate assertion.
api/device/v1alpha1/converter.go (1)
130-133: Consider handling zero-valuemetav1.TimeinToProtobufTimestamp.When
source.Timeis a zero-value,timestamppb.New()returns a Timestamp representing Unix epoch (1970-01-01). This may be acceptable, but if zero-value should represent "unset", consider returningnilinstead.🔎 Optional fix if nil is preferred for zero-value
func ToProtobufTimestamp(source metav1.Time) *timestamppb.Timestamp { + if source.IsZero() { + return nil + } return timestamppb.New(source.Time) }client-go/hack/overlays/client/versioned/integration_test.go (1)
64-86: Consider usingtestify/assertfor assertions.Per coding guidelines, use
testify/assertandtestify/requirefor assertions in Go tests. This provides better error messages and a consistent assertion style.🔎 Example refactor for the Get subtest
+ "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ... t.Run("Get", func(t *testing.T) { gpu, err := cs.DeviceV1alpha1().GPUs().Get(ctx, "gpu-1", metav1.GetOptions{}) - if err != nil { - t.Fatalf("Get failed: %v", err) - } - if gpu.Name != "gpu-1" { - t.Errorf("Expected gpu-1, got %s", gpu.Name) - } + require.NoError(t, err, "Get failed") + assert.Equal(t, "gpu-1", gpu.Name) })Based on coding guidelines, use
testify/assertandtestify/requirefor assertions in Go tests.client-go/examples/fake-server/main.go (1)
182-193: Add function comments for exported methods.Per coding guidelines, function comments are required for all exported Go functions. The gRPC service methods
GetGpu,ListGpus, andWatchGpusshould have documentation comments.🔎 Proposed documentation
+// GetGpu returns a single GPU by name, or NotFound if it doesn't exist. func (s *fakeServer) GetGpu(ctx context.Context, req *pb.GetGpuRequest) (*pb.GetGpuResponse, error) { +// ListGpus returns all GPUs in the fake server's inventory. func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { +// WatchGpus streams GPU events to the client. It first sends ADDED events for +// all existing GPUs (initial snapshot), then streams MODIFIED events as the +// simulated state changes. func (s *fakeServer) WatchGpus(req *pb.WatchGpusRequest, stream pb.GpuService_WatchGpusServer) error {Based on coding guidelines, function comments are required for all exported Go functions.
Also applies to: 195-208, 210-260
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
35-41: Consider nil check for defensive programming.The constructor doesn't check if
cis nil before callingc.ClientConn()andc.logger.WithName(). While this is a private function and callers should provide valid input, a defensive check could prevent panics.🔎 Optional defensive check
func newGPUs(c *DeviceV1alpha1Client) *gpus { + if c == nil { + panic("DeviceV1alpha1Client cannot be nil") + } return &gpus{ client: pb.NewGpuServiceClient(c.ClientConn()), logger: c.logger.WithName("gpus"), } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (49)
.coderabbit.yaml.gitattributes.gitignore.versions.yamlMakefileapi/Makefileapi/device/v1alpha1/converter.goapi/device/v1alpha1/doc.goapi/device/v1alpha1/gpu_conversion.goapi/device/v1alpha1/gpu_conversion_test.goapi/device/v1alpha1/gpu_types.goapi/device/v1alpha1/register.goapi/go.modapi/hack/boilerplate.go.txtapi/proto/device/v1alpha1/gpu.protoclient-go/DEVELOPMENT.mdclient-go/Makefileclient-go/README.mdclient-go/examples/README.mdclient-go/examples/basic-client/README.mdclient-go/examples/basic-client/main.goclient-go/examples/controller-shim/README.mdclient-go/examples/controller-shim/main.goclient-go/examples/fake-server/README.mdclient-go/examples/fake-server/main.goclient-go/examples/streaming-daemon/README.mdclient-go/examples/streaming-daemon/main.goclient-go/go.modclient-go/hack/apply-overlays.shclient-go/hack/boilerplate.go.txtclient-go/hack/boilerplate_overlay.go.txtclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/nvgrpc/client_conn.goclient-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/config.goclient-go/nvgrpc/config_test.goclient-go/nvgrpc/interceptors.goclient-go/nvgrpc/interceptors_test.goclient-go/nvgrpc/options.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/watcher_test.goclient-go/version/version.goclient-go/version/version_test.go
✅ Files skipped from review due to trivial changes (2)
- client-go/hack/boilerplate_overlay.go.txt
- api/hack/boilerplate.go.txt
🚧 Files skipped from review as they are similar to previous changes (26)
- client-go/hack/boilerplate.go.txt
- client-go/examples/README.md
- client-go/nvgrpc/client_conn.go
- client-go/nvgrpc/interceptors_test.go
- client-go/version/version_test.go
- client-go/nvgrpc/client_conn_test.go
- client-go/examples/streaming-daemon/main.go
- api/device/v1alpha1/gpu_conversion_test.go
- api/device/v1alpha1/register.go
- client-go/go.mod
- client-go/examples/basic-client/main.go
- client-go/hack/overlays/client/versioned/clientset.go
- Makefile
- api/device/v1alpha1/gpu_conversion.go
- client-go/nvgrpc/interceptors.go
- client-go/nvgrpc/config.go
- api/device/v1alpha1/gpu_types.go
- api/go.mod
- client-go/nvgrpc/options.go
- .coderabbit.yaml
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
- client-go/nvgrpc/watcher.go
- client-go/nvgrpc/config_test.go
- client-go/examples/fake-server/README.md
- client-go/examples/streaming-daemon/README.md
- client-go/hack/apply-overlays.sh
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goapi/device/v1alpha1/converter.goapi/device/v1alpha1/doc.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/examples/fake-server/main.goclient-go/examples/controller-shim/main.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/nvgrpc/watcher_test.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.go
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
.gitignoreclient-go/README.md.gitattributesclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/examples/basic-client/README.md.versions.yamlclient-go/version/version.goclient-go/Makefileclient-go/DEVELOPMENT.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.gitignore.gitattributes.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
.gitignoreclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go.versions.yamlclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/fake-server/main.goclient-go/examples/controller-shim/main.goclient-go/version/version.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/fake-server/main.goclient-go/examples/controller-shim/main.goclient-go/version/version.go
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
.versions.yamlapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/version/version.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `testify/assert` and `testify/require` for assertions in Go tests
Applied to files:
client-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
client-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Aim for >80% test coverage on critical paths in Go code
Applied to files:
client-go/nvgrpc/watcher_test.go
🧬 Code graph analysis (6)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/examples/fake-server/main.go (3)
client-go/nvgrpc/config.go (2)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
client-go/hack/overlays/client/versioned/integration_test.go (7)
commons/pkg/server/server.go (1)
NewServer(375-396)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
NewForConfigAndClient(39-44)New(58-63)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)node-drainer/pkg/config/config.go (1)
Duration(37-39)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (5)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
DeviceV1alpha1Client(15-18)api/device/v1alpha1/gpu_conversion.go (2)
FromProto(25-32)FromProtoList(43-48)client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🪛 LanguageTool
client-go/DEVELOPMENT.md
[style] ~77-~77: This phrase is redundant. Consider using “inside”.
Context: ... informers/) The directory structure inside of hack/overlays/ *must exactly mirror...
(OUTSIDE_OF)
🪛 markdownlint-cli2 (0.18.1)
client-go/DEVELOPMENT.md
10-10: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🔇 Additional comments (52)
.gitignore (1)
18-18: ✓ Appropriate addition to support code generation outputs.The addition of
client-go/bin/*mirrors the existingapi/bin/*rule and correctly excludes generated binaries from the client-go code-gen workflow, keeping version control clean.client-go/version/version.go (1)
22-35: LGTM! Clean version stamping implementation.The implementation correctly provides build-time version information and user-agent string generation. The GitVersion variable is properly set up for ldflags injection, and the UserAgent function correctly formats the string with version and platform information.
client-go/examples/controller-shim/README.md (3)
34-34: Unix socket path syntax is correct.The syntax
unix:///tmp/device-api.sockfollows gRPC's RFC 3986 URI syntax where the path must be absolute and the last of the three slashes is actually part of the path. This is the standard format for Go gRPC UDS connections.
37-37: No action needed. The Fake Server's README already clearly documents theNVIDIA_DEVICE_API_TARGETenvironment variable, its default value (/var/run/nvidia-device-api/device-api.sock), and when it must be exported. The controller-shim README's reference to this variable is well-supported by existing documentation.
54-54: Verify main.go exists with NewInformer implementation.The implementation note directs users to review
NewInformersetup inmain.go. This file exists in the same directory and contains a clear example of the gRPC/UDS informer injection pattern.client-go/nvgrpc/watcher_test.go (3)
179-190: LGTM! Minimal and correct runtime.Object implementation.
FakeObjectcorrectly implements theruntime.Objectinterface for testing. TheDeepCopyObjectmethod provides an adequate copy since bothTypeMetaandNameare value types.
192-195: LGTM! Simple and appropriate test data structure.The
testEventstruct cleanly represents event type and object pairs for test scenarios.
197-239: LGTM! Well-implemented test source with correct defensive programming.
FakeSourcecorrectly implements thenvgrpc.Sourceinterface:
Next()appropriately prioritizes queued errors before events and returnsio.EOFwhen exhaustedClose()safely handles multiple close calls with a select guard (lines 233-237)- The nil check on line 230 is defensive programming that protects against direct struct initialization bypassing
NewFakeSource()The implementation provides a clean, reusable test utility for validating Watcher behavior.
client-go/examples/controller-shim/main.go (4)
15-20: Package documentation is clear and well-structured.The package-level godoc effectively explains the controller-shim pattern and its integration with gRPC-backed informers.
71-112: Manager setup and cache customization are well-implemented.The custom
NewInformerhook correctly injects the gRPC-backed informer for GPU objects and falls back to a standard informer for other types. The indexer merging logic (lines 90-98) properly avoids conflicts by checking existing indexers before adding new ones.
45-63: Setup and initialization logic is well-structured.The logger setup, target determination from environment variables, and clientset initialization are all correctly implemented with appropriate error handling.
114-127: Reconciler registration and manager startup are correctly implemented.The reconciler is properly registered with the manager, and shutdown handling uses
ctrl.SetupSignalHandler()for proper context cancellation.client-go/examples/basic-client/README.md (1)
1-18: LGTM!Clear documentation covering client initialization, K8s-native verbs, and metadata inspection. The fake-server path is now correct at
../fake-server..gitattributes (1)
1-16: LGTM!Properly configured to hide generated code from GitHub PR diffs. The patterns correctly cover Kubernetes-generated helpers (
zz_generated.*.go), protobuf bindings (*.pb.go), and the generated client library paths.api/device/v1alpha1/doc.go (1)
1-19: LGTM!The package documentation follows Go conventions and includes the required
+groupNameannotation for Kubernetes code generators. The package-level godoc clearly describes the API schema definitions. As per coding guidelines, package-level documentation is required for all Go packages—this requirement is satisfied.client-go/README.md (1)
1-96: LGTM!Comprehensive and well-structured documentation covering:
- Clear experimental preview warning
- Kubernetes-native features (clientsets, informers, listers)
- Practical Quick Start example with idiomatic Go patterns
- Detailed deployment guidance for DaemonSets including volume mounts and security considerations
- Consistent socket path references throughout
The documentation effectively onboards users to the SDK. As per coding guidelines, using
client-gofor Kubernetes API interactions is the recommended approach, and this SDK follows that pattern.api/proto/device/v1alpha1/gpu.proto (2)
27-77: Well-designed metadata structure aligned with Kubernetes conventions.The new
ObjectMetaandListMetamessages properly subset the Kubernetes API machinery types, enablingresource_versionsupport for Watch semantics and optimistic concurrency. Field documentation is comprehensive as required by coding guidelines for Protocol Buffer messages.
152-167: LGTM!Adding
resource_versiontoListGpusRequestandWatchGpusRequestenables clients to list resources at a specific version and start watches from a consistent point, which is essential for proper cache synchronization.api/device/v1alpha1/converter.go (2)
23-104: Well-structured goverter interface with comprehensive field mappings.The
Converterinterface is cleanly annotated with goverter directives, properly ignoring protobuf internal fields (state,sizeCache,unknownFields) and Kubernetes-specific fields not present in the protobuf definitions. The field mappings betweenUuid/UUIDand metadata structures are correctly specified.
106-120: TypeMeta helpers now correctly return full APIVersion.The fix to use
SchemeGroupVersion.String()instead of.VersionensuresAPIVersionis properly formatted asdevice.nvidia.com/v1alpha1..versions.yaml (1)
49-50: Version additions are consistent with project dependencies.The
goverter: 'v1.9.2'andkubernetes_code_gen: 'v0.34.1'entries align with the code generation workflow and match the k8s.io/client-go version used in the project.client-go/DEVELOPMENT.md (1)
48-70: Excellent documentation of the code generation pipeline.The mermaid diagram clearly illustrates the flow from API definitions through the generators to the final SDK. The explanation of each component (client-gen, lister-gen, informer-gen, overlays) is concise and informative.
client-go/hack/overlays/client/versioned/integration_test.go (3)
33-62: Well-structured test setup with bufconn for in-process gRPC testing.The test correctly sets up an in-memory gRPC server using bufconn, creates a mock GPU service, and establishes a clientset connection. The context timeout and proper cleanup with
deferstatements are appropriate.
256-276: Mock server implementation is clean and thread-safe.The
mockGpuServercorrectly usessync.RWMutexfor concurrent access protection, maintains in-memory GPU state, and provides a channel-based mechanism for injecting watch events during tests.
298-332: WatchGpus correctly implements initial snapshot followed by live updates.The implementation properly sends the initial state as ADDED events under a read lock, then streams live events from the channel until the context is cancelled.
client-go/examples/fake-server/main.go (3)
15-20: Good package-level documentation.The package documentation clearly explains the purpose of this fake server for local testing and development.
135-169: Simulation logic is well-implemented.The
simulateChangesfunction correctly uses a ticker for periodic updates, properly locks when modifying state, incrementsResourceVersionfor watch semantics, and broadcasts updates to all connected watchers.
171-180: Non-blocking broadcast prevents slow consumers from blocking the simulator.The
defaultcase in the select statement ensures that slow or stuck watch streams don't block the simulation loop. This is a good resilience pattern for a fake server.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (7)
9-12: LGTM: Clean interface design.The interface follows standard Kubernetes client-go patterns by exposing the gRPC connection and resource-specific getters.
14-18: LGTM: Well-structured client.The client struct appropriately encapsulates the gRPC connection and logger with private fields.
20-22: LGTM: Standard accessor pattern.The GPUs() method correctly delegates to the newGPUs constructor following client-go conventions.
24-35: LGTM: Safe config handling with shallow copy.The constructor correctly creates a shallow copy of the config to prevent mutation and properly handles errors from the connection creation.
46-55: LGTM: Standard OrDie pattern.The constructor correctly implements the Kubernetes-style "OrDie" pattern for initialization-time configuration.
57-63: LGTM: Appropriate fallback constructor.The New constructor correctly handles the case where a connection is provided directly, using a discarded logger as a sensible default.
65-73: LGTM: Proper nil-safety.The ClientConn accessor correctly handles the nil receiver case, preventing panics when called on a nil client pointer.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (5)
15-19: LGTM: Standard getter interface.The GPUsGetter interface follows Kubernetes client-go conventions for resource-specific getters.
29-33: LGTM: Clean struct design.The gpus struct appropriately encapsulates the gRPC service client and logger.
43-56: LGTM: Correct Get implementation.The method properly handles the gRPC call, converts the protobuf response to internal types, and logs at an appropriate verbosity level.
58-71: LGTM: Proper List implementation.The method correctly passes the ResourceVersion from ListOptions, converts the response, and logs useful metadata.
73-87: LGTM: Robust Watch implementation.The method properly handles context cancellation, error cleanup, and integrates with the nvgrpc watcher pattern. The use of ResourceVersion from ListOptions ensures correct watch semantics.
api/Makefile (6)
19-60: LGTM: Well-structured configuration.The configuration section properly defines all necessary variables including API_PKGS_COMMA (which was flagged in a previous review but is now correctly defined on line 37). The GO_VERSION extraction with fallback is a good practice.
62-79: LGTM: Clean tooling setup.The tool configuration properly uses yq to centralize version management and includes a helpful error message if yq is not installed.
86-109: LGTM: Proper target dependencies.The target chain correctly ensures code generation runs before build and test, and appropriately excludes generated code from test coverage.
112-141: LGTM: Robust code generation workflow.The generation targets properly handle per-version code generation with appropriate clean dependencies and correct use of API_PKGS_COMMA.
143-167: LGTM: Comprehensive cleanup targets.The hierarchical clean targets (clean vs purge) provide appropriate granularity for cleanup operations.
171-205: LGTM: Solid tool installation pattern.The go-install-tool macro correctly handles versioned tool binaries with symlinks and ensures the correct Go toolchain is used for installation.
client-go/Makefile (6)
19-67: LGTM: Comprehensive configuration.The configuration properly sets up module paths, API versions, build flags for version embedding, and Go version detection with appropriate fallback.
69-83: LGTM: Consistent tool versioning.The tool configuration follows the same yq-based version management pattern as the api/Makefile, promoting consistency across the codebase.
89-113: LGTM: Well-organized build workflow.The targets properly chain dependencies and appropriately exclude generated code and examples from testing while including version flags in the build.
115-149: LGTM: Standard Kubernetes code generation.The client-gen, lister-gen, and informer-gen targets follow standard Kubernetes patterns with appropriate flags and output configuration. The copy-overlays step ensures custom code is properly applied after generation.
151-176: LGTM: Comprehensive cleanup.The clean targets provide appropriate granularity with separate targets for each generated component and a purge option for complete cleanup.
180-213: LGTM: Consistent tool installation.The install-tools targets and go-install-tool macro follow the same robust pattern as the api/Makefile, ensuring consistent tool management across modules.
a1fae68 to
e12477e
Compare
Signed-off-by: Dan Huenecke <[email protected]>
e12477e to
1538ceb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (8)
client-go/nvgrpc/watcher_test.go (1)
154-177: Critical: Race condition due totime.Sleepin test.Line 160 uses
time.Sleep(10 * time.Millisecond)to "allow the receive loop to start," creating a race condition. There's no guarantee the goroutine has started or reached the desired state, making this test flaky on slower systems or under load.🔎 Recommended fix: Remove sleep and rely on observable behavior
Remove the sleep entirely and rely on the observable effects of
Stop():func TestWatcher_Stop(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) source := NewFakeSource() w := NewWatcher(source, cancel, logr.Discard()) - // Allow the receive loop to start - time.Sleep(10 * time.Millisecond) w.Stop() select { case <-ctx.Done(): case <-time.After(time.Second): t.Error("context not cancelled after Stop()") } select { case _, ok := <-w.ResultChan(): if ok { t.Error("ResultChan not closed") } case <-time.After(time.Second): t.Error("ResultChan hang") } }The timeouts in the select statements provide sufficient protection against hangs while verifying that
Stop()cancels the context and closesResultChan.api/proto/device/v1alpha1/gpu.proto (1)
27-51: Inconsistent indentation in proto comments.Lines 35-37 within the ObjectMeta comment block use tabs for indentation, while the surrounding comment lines use spaces. This inconsistency should be normalized to use spaces throughout for better readability and consistency with protobuf style conventions.
🔎 Proposed fix
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/examples/basic-client/README.md (1)
20-38: Socket path mismatch between instructions and expected output.Line 24 instructs users to set
NVIDIA_DEVICE_API_TARGET=unix:///tmp/device-api.sock, but the expected output at line 31 displaysunix:///tmp/nvidia-device-api.sock. These paths must match for the example to be accurate.🔎 Proposed fix
-"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///tmp/nvidia-device-api.sock" +"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///tmp/device-api.sock"client-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Unsafe call tot.Errorffrom a goroutine.Calling
t.Errorf(or anytmethod) from a goroutine is unsafe and can cause race conditions. Thetestingpackage is not designed for concurrent access to*testing.T.🔎 Proposed fix using an error channel
+ errCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + errCh <- err } + close(errCh) }() if !c.WaitForCacheSync(ctx) { t.Fatal("Controller-runtime cache failed to sync") } + + // Check for startup errors after sync + select { + case err := <-errCh: + if err != nil { + t.Fatalf("Cache failed to start: %v", err) + } + default: + }client-go/examples/streaming-daemon/main.go (1)
146-148: Misleading log message.The log message says "context timeout reached" but the context is created from
signal.NotifyContext(line 93), which cancels on signals (SIGINT/SIGTERM), not on timeout.🔎 Proposed fix
case <-ctx.Done(): - logger.Info("context timeout reached, stopping watch") + logger.Info("received shutdown signal, stopping watch") returnclient-go/Makefile (1)
187-187: Declare thetoolstarget as PHONY.The
toolstarget should be declared.PHONYsince it doesn't produce a file output and is used as a convenience alias for tool binaries.Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)client-go/examples/controller-shim/main.go (2)
65-69: The informer factory is never started.The comment on line 67 states the Manager will start the injected informer, but controller-runtime only starts informers created through its own cache machinery. The gRPC-backed informer from
factoryneeds to be started explicitly; otherwise, the cache will never populate and reconciliation won't occur.Suggested fix
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + // Start the factory in the background before the manager attempts to use the cache. + stopCh := make(chan struct{}) + defer close(stopCh) + factory.Start(stopCh)
135-152: Add godoc comments for exported methods.The exported methods
ReconcileandSetupWithManagerlack documentation. As per coding guidelines, function comments are required for all exported Go functions.Suggested additions
+// Reconcile retrieves the requested GPU resource from the gRPC-backed cache +// and logs its name and UUID. It returns without error if the GPU is not found. func (r *GPUReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := ctrl.LoggerFrom(ctx) var gpu devicev1alpha1.GPU // The Get call is transparently routed through the injected gRPC-backed informer. if err := r.Get(ctx, req.NamespacedName, &gpu); err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } log.Info("Reconciled GPU", "name", gpu.Name, "uuid", gpu.Spec.UUID) return ctrl.Result{}, nil } +// SetupWithManager registers this reconciler with the provided manager, +// configuring it to watch GPU resources. func (r *GPUReconciler) SetupWithManager(mgr ctrl.Manager) error {
🧹 Nitpick comments (5)
client-go/nvgrpc/watcher_test.go (2)
179-190: Consider adding godoc for exported test utility.
FakeObjectis an exported type but lacks a doc comment. While test utilities have lower documentation requirements, adding a brief comment would improve clarity for developers using this in other tests.As per coding guidelines, exported functions should have doc comments.
🔎 Suggested doc comment
+// FakeObject is a minimal implementation of runtime.Object for testing. +// It contains only a TypeMeta and Name field. type FakeObject struct { metav1.TypeMeta Name string }
197-239: Consider adding godoc for exported test utilities.
FakeSourceandNewFakeSourceare exported but lack doc comments. Adding brief documentation would help developers understand their purpose and usage in tests.As per coding guidelines, exported functions should have doc comments.
🔎 Suggested doc comments
+// FakeSource implements nvgrpc.Source for testing. +// It allows tests to inject predetermined events and errors to verify Watcher behavior. type FakeSource struct { events chan testEvent errs []error done chan struct{} } +// NewFakeSource creates a new FakeSource with initialized channels. func NewFakeSource() *FakeSource { return &FakeSource{ events: make(chan testEvent, 10), done: make(chan struct{}), } }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
9-12: Add godoc for exported interface.The
DeviceV1alpha1Interfaceis exported but lacks documentation. As per coding guidelines, function comments are required for all exported Go functions (interfaces included).Suggested addition
+// DeviceV1alpha1Interface provides access to resources in the device.nvidia.com/v1alpha1 API group. type DeviceV1alpha1Interface interface { ClientConn() grpc.ClientConnInterface GPUsGetter }
37-44: Consider validating config in NewForConfigAndClient.While
NewForConfigvalidates throughnvgrpc.ClientConnFor, direct callers ofNewForConfigAndClientbypass validation. Consider adding a nil check or validation call for defensive programming.Proposed validation addition
func NewForConfigAndClient(c *nvgrpc.Config, conn grpc.ClientConnInterface) (*DeviceV1alpha1Client, error) { + if c == nil { + return nil, fmt.Errorf("config cannot be nil") + } return &DeviceV1alpha1Client{ conn: conn, logger: c.GetLogger().WithName("device.v1alpha1"), }, nil }api/Makefile (1)
36-37: Minor formatting: missing space after#in comment.Line 36 has
#Helperinstead of# Helperfor consistency with other comments.Proposed fix
-#Helper for tools that need comma-separated package paths +# Helper for tools that need comma-separated package paths API_PKGS_COMMA := $(subst $(SPACE),$(COMMA),$(API_PKGS))
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (49)
.coderabbit.yaml.gitattributes.gitignore.versions.yamlMakefileapi/Makefileapi/device/v1alpha1/converter.goapi/device/v1alpha1/doc.goapi/device/v1alpha1/gpu_conversion.goapi/device/v1alpha1/gpu_conversion_test.goapi/device/v1alpha1/gpu_types.goapi/device/v1alpha1/register.goapi/go.modapi/hack/boilerplate.go.txtapi/proto/device/v1alpha1/gpu.protoclient-go/DEVELOPMENT.mdclient-go/Makefileclient-go/README.mdclient-go/examples/README.mdclient-go/examples/basic-client/README.mdclient-go/examples/basic-client/main.goclient-go/examples/controller-shim/README.mdclient-go/examples/controller-shim/main.goclient-go/examples/fake-server/README.mdclient-go/examples/fake-server/main.goclient-go/examples/streaming-daemon/README.mdclient-go/examples/streaming-daemon/main.goclient-go/go.modclient-go/hack/apply-overlays.shclient-go/hack/boilerplate.go.txtclient-go/hack/boilerplate_overlay.go.txtclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/nvgrpc/client_conn.goclient-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/config.goclient-go/nvgrpc/config_test.goclient-go/nvgrpc/interceptors.goclient-go/nvgrpc/interceptors_test.goclient-go/nvgrpc/options.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/watcher_test.goclient-go/version/version.goclient-go/version/version_test.go
✅ Files skipped from review due to trivial changes (2)
- api/hack/boilerplate.go.txt
- .gitattributes
🚧 Files skipped from review as they are similar to previous changes (23)
- .versions.yaml
- client-go/version/version_test.go
- .coderabbit.yaml
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go
- client-go/nvgrpc/interceptors_test.go
- api/device/v1alpha1/doc.go
- client-go/nvgrpc/interceptors.go
- client-go/examples/controller-shim/README.md
- client-go/hack/boilerplate.go.txt
- client-go/hack/overlays/client/versioned/clientset.go
- client-go/nvgrpc/client_conn_test.go
- client-go/examples/fake-server/README.md
- client-go/hack/apply-overlays.sh
- client-go/nvgrpc/client_conn.go
- client-go/examples/fake-server/main.go
- api/device/v1alpha1/gpu_types.go
- client-go/nvgrpc/watcher.go
- client-go/examples/basic-client/main.go
- client-go/version/version.go
- client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go
- client-go/examples/streaming-daemon/README.md
- .gitignore
- client-go/nvgrpc/options_test.go
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
api/device/v1alpha1/gpu_conversion_test.goapi/device/v1alpha1/gpu_conversion.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/streaming-daemon/main.goclient-go/nvgrpc/config.goclient-go/examples/controller-shim/main.goclient-go/nvgrpc/watcher_test.goapi/device/v1alpha1/register.goclient-go/nvgrpc/config_test.goapi/device/v1alpha1/converter.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/options.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
api/device/v1alpha1/gpu_conversion_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
api/go.modclient-go/go.mod
🧠 Learnings (24)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/examples/basic-client/README.mdclient-go/examples/README.mdclient-go/DEVELOPMENT.mdapi/go.modclient-go/README.mdclient-go/go.modclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/boilerplate_overlay.go.txtclient-go/Makefile
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In Go tests across the repository, avoid introducing the testify dependency for simple equality/inequality checks. Use the standard testing package assertions (t.Error, t.Errorf, t.Fatal, etc.) for straightforward checks. Reserve third-party assertion libraries for complex scenarios that require richer diagnostics or expressive matchers.
Applied to files:
api/device/v1alpha1/gpu_conversion_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/README.mdclient-go/go.modclient-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/controller-shim/main.goMakefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/streaming-daemon/main.goclient-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goapi/go.modclient-go/examples/controller-shim/main.goclient-go/go.modclient-go/nvgrpc/watcher_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/examples/streaming-daemon/main.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
api/go.modclient-go/go.modMakefileapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
api/go.modclient-go/go.modMakefile
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In the NVIDIA/NVSentinel repository, prefer not to introduce a dependency on `stretchr/testify` for simple comparison assertions in Go tests. Use standard `testing` package assertions (t.Error, t.Errorf, etc.) for straightforward checks.
Applied to files:
api/go.modclient-go/go.mod
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/examples/controller-shim/main.goclient-go/nvgrpc/options.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/go.modclient-go/nvgrpc/options.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `testify/assert` and `testify/require` for assertions in Go tests
Applied to files:
client-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
client-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Aim for >80% test coverage on critical paths in Go code
Applied to files:
client-go/nvgrpc/watcher_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
client-go/hack/boilerplate_overlay.go.txt
🧬 Code graph analysis (9)
api/device/v1alpha1/gpu_conversion.go (2)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/hack/overlays/client/versioned/integration_test.go (4)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/config.go (1)
client-go/version/version.go (1)
UserAgent(28-35)
client-go/examples/controller-shim/main.go (3)
client-go/nvgrpc/config.go (2)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/nvgrpc/watcher_test.go (1)
client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
api/device/v1alpha1/register.go (1)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (4)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (2)
GPUsGetter(17-19)GPUInterface(22-27)client-go/hack/overlays/client/versioned/clientset.go (4)
NewForConfig(32-44)NewForConfigAndClient(48-65)NewForConfigOrDie(69-76)New(79-83)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (5)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
DeviceV1alpha1Client(15-18)api/device/v1alpha1/gpu_conversion.go (2)
FromProto(25-32)FromProtoList(43-48)client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🔇 Additional comments (55)
client-go/nvgrpc/watcher_test.go (1)
31-58: Past testify suggestion conflicts with repository learning.A previous review comment suggested using
testify/assertandtestify/requirefor these tests. However, based on learnings from this same PR (pteranodan, 2025-12-22), the repository policy is to avoid introducing testify for simple equality/inequality checks and to use standardtestingpackage assertions instead.The current implementation using
t.Fatalf,t.Errorf, etc., aligns with this learning and should be retained.Based on learnings, repository prefers standard library assertions for simple checks.
client-go/hack/boilerplate_overlay.go.txt (1)
1-16: LGTM: Proper boilerplate for generated overlays.The Apache 2.0 license header and generated-file notice are correctly formatted for the overlay code-generation workflow.
client-go/README.md (1)
1-94: Excellent documentation for the client-go SDK.The README provides comprehensive coverage of installation, usage patterns, deployment considerations, and development workflows. The experimental warning is appropriately prominent, and the examples table clearly guides users to the right integration pattern.
api/go.mod (1)
1-34: Well-structured dependency management.The module correctly declares
k8s.io/apimachineryas a direct dependency (line 16) and maintains a clean separation between direct and indirect requires. The Go version bump to 1.25.5 ensures the latest patch-level fixes are included.api/device/v1alpha1/register.go (1)
15-44: Idiomatic Kubernetes API registration.The implementation correctly follows Kubernetes API machinery patterns: proper SchemeGroupVersion setup, Resource helper for GroupResource derivation, and standard SchemeBuilder initialization. The type registration includes both GPU and GPUList with metav1.AddToGroupVersion for complete scheme integration.
Based on coding guidelines, this aligns with the requirement to use
client-gofor Kubernetes API interactions.client-go/go.mod (1)
1-74: Dependencies properly configured.The module structure is well-organized with:
- Latest Go patch version (1.25.5) for security fixes
- Consistent Kubernetes module versions (all at v0.34.1)
- Proper local module replacement using canonical v0.0.0 format
- Clear separation of direct and indirect dependencies
All previously identified issues have been successfully resolved.
client-go/DEVELOPMENT.md (1)
1-105: Comprehensive development guide.The documentation effectively covers the complete development workflow including:
- Clear prerequisite requirements
- Step-by-step code generation process with helpful tips
- Well-structured pipeline visualization using Mermaid
- Proper warnings about not editing generated files directly
- Detailed overlay pattern explanation
The guide provides developers with all necessary context to understand and contribute to the SDK's code-generation workflow.
api/device/v1alpha1/gpu_conversion_test.go (3)
30-43: LGTM! Nil handling tests are correct.The nil safety tests correctly verify that conversion helpers return nil for nil inputs, preventing potential nil pointer dereferences.
45-88: LGTM! Round-trip conversion test is well-structured.The test validates critical conversion behaviors including metadata transformation, ResourceVersion propagation, and uses protocmp for accurate protobuf comparison.
90-153: LGTM! GPUList conversion test has good coverage.The test validates list-level metadata, nested conditions with timestamps, and optional fields like RecommendedAction, ensuring robust conversion behavior.
client-go/nvgrpc/config_test.go (3)
20-59: LGTM! Target precedence test is well-structured.The table-driven test correctly validates the precedence order: explicit argument > environment variable > default. Uses standard testing package as per repository preference.
61-80: LGTM! UserAgent tests validate default and custom behavior.The tests correctly verify that empty UserAgent is populated with a default value, while custom values are preserved.
82-120: LGTM! Validation tests cover required fields.The table-driven validation tests correctly verify that both Target and UserAgent are required fields, returning errors when either is missing.
client-go/examples/streaming-daemon/main.go (2)
15-20: LGTM! Package documentation is clear and comprehensive.The package-level godoc effectively explains the example's purpose, demonstrating custom interceptors, persistent watch streams, and gRPC connection lifecycle management.
50-53: LGTM! Correct use of nvgrpc constants.The code properly uses
nvgrpc.NvidiaDeviceAPITargetEnvVarandnvgrpc.DefaultNvidiaDeviceAPISocket, ensuring consistency with the SDK defaults.api/device/v1alpha1/gpu_conversion.go (2)
15-22: LGTM! Build tag and singleton pattern are appropriate.The
!goverterbuild tag correctly excludes this file during code generation, and the singleton converter instance provides a clean adapter layer.
24-56: LGTM! Conversion helpers are nil-safe.All four conversion helpers (FromProto, ToProto, FromProtoList, ToProtoList) correctly check for nil inputs and delegate to the singleton converter, providing a clean public API for GPU conversions.
client-go/nvgrpc/options.go (2)
22-29: LGTM! Functional options pattern correctly implemented.The DialOption type and internal dialOptions struct provide a clean, extensible configuration mechanism for the gRPC client.
31-50: LGTM! Option functions are well-documented and correct.All three option functions (WithLogger, WithUnaryInterceptor, WithStreamInterceptor) have proper godoc comments and correctly mutate the dialOptions struct.
client-go/hack/overlays/client/versioned/integration_test.go (6)
33-62: LGTM! Test setup is correct.The test properly sets up an in-process gRPC server using bufconn, creating a realistic end-to-end testing environment without external dependencies.
64-86: LGTM! Get and List tests validate basic operations.The tests correctly verify clientset Get and List operations, including metadata like ResourceVersion.
88-129: LGTM! Watch flow test validates streaming behavior.The test correctly verifies initial snapshot delivery and live event propagation through the watch stream.
131-182: LGTM! Informer sync test validates caching behavior.The test correctly instantiates the informer before starting the factory and validates cache synchronization with polling for eventual consistency.
194-203: LGTM! NewInformer fallback prevents nil pointer issues.The fallback to
cache.NewSharedIndexInformerfor non-GPU objects correctly prevents potential nil pointer dereferences, addressing the previous review concern.
254-336: LGTM! Mock server implementation is thread-safe.The mock server correctly uses
sync.RWMutexfor concurrent access, properly handles context cancellation, and provides realistic watch stream behavior with initial snapshots and live events.client-go/examples/controller-shim/main.go (4)
15-20: LGTM on package documentation.The package-level godoc clearly explains the purpose of this example: demonstrating a Kubernetes controller using gRPC-backed informers to bypass the standard API server.
45-63: LGTM on clientset initialization.The setup correctly reads the target from the environment variable with a sensible default, and initializes the gRPC-backed clientset with proper error handling.
71-112: LGTM on Manager configuration with custom cache injection.The custom
MapperProviderandNewInformerimplementation correctly inject the gRPC-backed informer for GPU resources while falling back to standard informers for other types. The indexer merging logic properly handles conflicts.
130-133: LGTM on GPUReconciler type definition.The reconciler embeds
client.Clientfollowing the controller-runtime pattern.client-go/nvgrpc/config.go (5)
26-38: LGTM on constant definitions.The exported constants for environment variable, default socket path, and keepalive settings are well-documented and provide sensible defaults.
40-49: LGTM on Config struct definition.The struct clearly documents its fields. The unexported
loggerfield with a getter pattern is appropriate.
51-67: LGTM on Default() implementation.The method correctly applies defaults from environment variables and fallback values, following the expected precedence.
69-80: LGTM on Validate() implementation.The validation correctly checks for required fields and returns descriptive errors with guidance on fixing the issue.
82-89: LGTM on GetLogger() implementation.The defensive nil-sink check ensures a usable logger is always returned.
api/device/v1alpha1/converter.go (3)
23-104: LGTM on Converter interface definition.The interface is well-documented with goverter annotations for automatic code generation. The field mappings and ignores are correctly specified for bidirectional proto ↔ Go type conversions.
106-120: LGTM on TypeMeta helper functions.The functions correctly use
SchemeGroupVersion.String()to produce the fullgroup/versionformat (e.g.,device.nvidia.com/v1alpha1) as required by KubernetesTypeMeta.APIVersion.
122-133: LGTM on timestamp conversion functions.
FromProtobufTimestampcorrectly handles nil input by returning a zero-valuemetav1.Time.ToProtobufTimestampdelegates totimestamppb.Newappropriately.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (3)
14-22: LGTM on DeviceV1alpha1Client struct and GPUs accessor.The struct and accessor are well-documented and follow the standard client-go patterns.
24-35: LGTM on NewForConfig implementation.The function creates a shallow copy to avoid mutation and delegates to
nvgrpc.ClientConnFor, which internally handles defaulting and validation.
46-73: LGTM on remaining constructor variants and ClientConn accessor.
NewForConfigOrDie,New, andClientConnfollow standard client-go patterns with appropriate panic behavior and nil-safety.api/Makefile (6)
19-37: LGTM on string manipulation helpers and API configuration.The variable definitions for comma-separated versions and package paths are correctly implemented. The
API_PKGS_COMMAvariable is now properly defined.
55-59: LGTM on Go version resolution.The fallback from
toolchaindirective togo env GOVERSIONensures compatibility across different Go module configurations.
96-100: LGTM on code-gen target.The target correctly chains dependencies and runs
go mod tidyafter generation.
111-125: LGTM on protos-generate target.The per-version loop correctly generates protobuf bindings with proper plugin paths and output options.
127-141: LGTM on deepcopy-gen and conversion-gen targets.Both targets correctly use the per-version configuration and properly clean before regenerating.
194-205: LGTM on go-install-tool macro.The macro correctly handles versioned tool installation with symlinks for version management and uses
GOTOOLCHAINfor consistent Go version.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (4)
29-41: LGTM on gpus struct and constructor.The struct correctly wraps the gRPC client with a logger, and the constructor appropriately derives the logger from the parent client.
43-56: LGTM on Get implementation.The method correctly calls the gRPC service, converts the response using
FromProto, and logs at an appropriate verbosity level.
58-71: LGTM on List implementation.The method correctly passes
ResourceVersionfor list consistency and logs the result count.
73-87: LGTM on Watch implementation.The method correctly creates a cancellable context, handles stream creation errors by calling
cancel(), and wraps the stream withnvgrpc.NewWatcher. This follows best practices for watch implementations.client-go/Makefile (5)
19-47: LGTM on configuration section.The variable definitions for modules, API versions, version flags, and linker flags are well-structured and follow the same patterns as the api/Makefile.
63-67: LGTM on Go version resolution.The fallback logic from
toolchaindirective togo env GOVERSIONensures compatibility.
100-113: LGTM on code-gen, build, and test targets.The targets correctly chain dependencies and exclude generated/example code from compilation and testing where appropriate.
115-149: LGTM on client-gen, lister-gen, informer-gen, and copy-overlays targets.The generation targets correctly invoke the respective tools with proper flags and the overlay copying script.
198-213: LGTM on go-install-tool macro.The macro correctly handles versioned tool installation with symlinks and uses
GOTOOLCHAINfor consistent Go version.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
Outdated
Show resolved
Hide resolved
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
Outdated
Show resolved
Hide resolved
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go
Outdated
Show resolved
Hide resolved
346284e to
d97ed84
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (15)
client-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Unsafe use oft.Errorffrom goroutine.Calling
t.Errorffrom a goroutine is unsafe and can cause data races or panics if the test completes before the goroutine executes. Sincec.Start(ctx)blocks until context cancellation, any error would indicate a real problem that should fail the test.🔎 Proposed fix using an error channel
+ errCh := make(chan error, 1) go func() { if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) + errCh <- err } + close(errCh) }() if !c.WaitForCacheSync(ctx) { t.Fatal("Controller-runtime cache failed to sync") } + + // Check for startup errors after sync + select { + case err := <-errCh: + if err != nil { + t.Fatalf("Cache failed to start: %v", err) + } + default: + }client-go/nvgrpc/watcher.go (1)
15-30: Missing required package-level documentation.Per coding guidelines, all Go packages must have package-level godoc comments. This is especially important for public packages like
nvgrpcthat provide reusable utilities.🔎 Proposed fix
+// Package nvgrpc provides utilities for building Kubernetes-style watch interfaces +// over gRPC streaming connections. It includes connection management, interceptors, +// and a Watcher implementation that bridges gRPC streams to the standard +// k8s.io/apimachinery/pkg/watch.Interface. + package nvgrpcBased on coding guidelines, package-level godoc is required for all Go packages.
client-go/version/version.go (1)
15-15: Add package-level godoc comment.The coding guidelines require package-level godoc for all Go packages. This comment was raised in a previous review and remains unaddressed.
🔎 Suggested addition
+// Package version provides build-time version information and user-agent +// string generation for the nvidia-device-api-client. package versionclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
25-27: For server-streaming RPCs,CloseSend()is a no-op.This was raised in a previous review. For server-streaming RPCs like
WatchGpus, the client only receives messages and doesn't send after the initial request. While callingCloseSend()is not harmful (it's effectively a no-op), relying on context cancellation is the idiomatic approach for cleanup.🔎 Suggested fix
func (a *gpuStreamAdapter) Close() error { - return a.stream.CloseSend() + // For server-streaming RPCs, cleanup is handled by context cancellation. + // CloseSend() is a no-op since the client doesn't send after the initial request. + return nil }client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-7: Add package-level godoc comment.This was raised in a previous review and remains unaddressed. As per coding guidelines, package-level godoc is required.
🔎 Suggested documentation
+// Package fake provides fake implementations of the device v1alpha1 client +// for testing purposes. These fakes use an in-memory ObjectTracker instead +// of actual gRPC connections. package fake
13-15: Add function comment for exported method.This was raised in a previous review and remains unaddressed. As per coding guidelines, function comments are required for all exported Go functions.
🔎 Suggested documentation
+// GPUs returns a fake GPUInterface for testing GPU operations +// without requiring an actual gRPC connection. func (c *FakeDeviceV1alpha1) GPUs() v1alpha1.GPUInterface {client-go/examples/streaming-daemon/main.go (1)
146-148: Fix misleading log message.This was raised in a previous review. The log message says "context timeout reached" but the context is created from
signal.NotifyContext(line 93) which cancels on SIGINT/SIGTERM signals, not on timeout.🔎 Suggested fix
case <-ctx.Done(): - logger.Info("context timeout reached, stopping watch") + logger.Info("received shutdown signal, stopping watch") returnapi/proto/device/v1alpha1/gpu.proto (1)
27-51: Inconsistent indentation in comment blocks (partial fix).Lines 35-37 still use tabs while the surrounding lines use spaces. This was raised in a previous review and appears to be partially addressed (lines 47-48 now use spaces correctly).
🔎 Suggested fix for remaining inconsistency
// resource_version represents the internal version of this object. // // Value must be treated as opaque by clients and passed unmodified back to the server. - // Populated by the system. - // Read-only. - // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + // Populated by the system. + // Read-only. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency string resource_version = 2;client-go/examples/controller-shim/main.go (1)
135-152: Add godoc comments for exported methods.This was raised in a previous review. As per coding guidelines, function comments are required for all exported Go functions.
🔎 Suggested additions
+// Reconcile retrieves the requested GPU resource from the gRPC-backed cache +// and logs its name and UUID. It returns without error if the GPU is not found. func (r *GPUReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {+// SetupWithManager registers this reconciler with the provided manager, +// configuring it to watch GPU resources. func (r *GPUReconciler) SetupWithManager(mgr ctrl.Manager) error {client-go/examples/fake-server/main.go (1)
195-208:ListMetais not populated in the response.This was raised in a previous review. The
GpuListresponse doesn't includemetadata.resource_version, which is needed for clients to establish a watch from a consistent point (List-then-Watch pattern).🔎 Suggested fix
func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { s.mu.RLock() defer s.mu.RUnlock() gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: "1", // Or track a global version + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), }api/device/v1alpha1/gpu_types.go (1)
15-15: Package-level documentation still missing.The package-level godoc required by coding guidelines remains absent. This was flagged in a previous review.
Based on coding guidelines: Package-level godoc required for all Go packages.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
1-1: Package-level documentation still missing.The package-level godoc required by coding guidelines remains absent. This was flagged in a previous review.
Based on coding guidelines: Package-level godoc required for all Go packages.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (2)
1-1: Package-level documentation still missing.The package-level godoc required by coding guidelines remains absent. This was flagged in a previous review.
Based on coding guidelines: Package-level godoc required for all Go packages.
21-27:GPUExpansioninterface is still undefined - code will not compile.The
GPUInterfaceembedsGPUExpansion(line 26), but this interface is not defined anywhere in the codebase. This is a compilation blocker that was flagged in previous reviews.🔎 Proposed fix
Create a new file
gpu_expansion.goin the same directory:package v1alpha1 // GPUExpansion allows for extension of GPU interface. type GPUExpansion interface{}client-go/Makefile (1)
187-187: Declaretoolstarget as.PHONY.The
toolstarget should be declared.PHONYsince it doesn't produce a file output and is used as a convenience alias for tool binaries.🔎 Proposed fix
+.PHONY: tools tools: $(CLIENT_GEN) $(LISTER_GEN) $(INFORMER_GEN)
🧹 Nitpick comments (3)
api/device/v1alpha1/register.go (2)
15-21: Add package-level godoc comment.As per coding guidelines, package-level godoc is required for all Go packages.
🔎 Suggested documentation
+// Package v1alpha1 contains API types for the device.nvidia.com/v1alpha1 API group. +// It provides GPU and GPUList resources for representing NVIDIA GPU devices. package v1alpha1
25-27: Add function comment for exported function.As per coding guidelines, function comments are required for all exported Go functions.
🔎 Suggested documentation
+// Resource returns the schema.GroupResource for the given resource name +// within the device.nvidia.com API group. func Resource(resource string) schema.GroupResource {client-go/examples/fake-server/main.go (1)
262-268: Consider documenting UUID generation approach.The
generateGPUUUIDfunction usesmath/randwhich is not cryptographically secure, but this is acceptable for a fake server. Consider adding a brief comment noting this is for testing purposes only.🔎 Suggested documentation
+// generateGPUUUID creates a pseudo-random UUID for fake GPU resources. +// Uses math/rand (not crypto-secure) which is acceptable for testing purposes. func generateGPUUUID() string {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (49)
.coderabbit.yaml.gitattributes.gitignore.versions.yamlMakefileapi/Makefileapi/device/v1alpha1/converter.goapi/device/v1alpha1/doc.goapi/device/v1alpha1/gpu_conversion.goapi/device/v1alpha1/gpu_conversion_test.goapi/device/v1alpha1/gpu_types.goapi/device/v1alpha1/register.goapi/go.modapi/hack/boilerplate.go.txtapi/proto/device/v1alpha1/gpu.protoclient-go/DEVELOPMENT.mdclient-go/Makefileclient-go/README.mdclient-go/examples/README.mdclient-go/examples/basic-client/README.mdclient-go/examples/basic-client/main.goclient-go/examples/controller-shim/README.mdclient-go/examples/controller-shim/main.goclient-go/examples/fake-server/README.mdclient-go/examples/fake-server/main.goclient-go/examples/streaming-daemon/README.mdclient-go/examples/streaming-daemon/main.goclient-go/go.modclient-go/hack/apply-overlays.shclient-go/hack/boilerplate.go.txtclient-go/hack/boilerplate_overlay.go.txtclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/nvgrpc/client_conn.goclient-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/config.goclient-go/nvgrpc/config_test.goclient-go/nvgrpc/interceptors.goclient-go/nvgrpc/interceptors_test.goclient-go/nvgrpc/options.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/watcher_test.goclient-go/version/version.goclient-go/version/version_test.go
✅ Files skipped from review due to trivial changes (4)
- api/hack/boilerplate.go.txt
- client-go/examples/controller-shim/README.md
- client-go/hack/boilerplate_overlay.go.txt
- api/device/v1alpha1/doc.go
🚧 Files skipped from review as they are similar to previous changes (22)
- .coderabbit.yaml
- client-go/hack/apply-overlays.sh
- .versions.yaml
- api/device/v1alpha1/gpu_conversion_test.go
- client-go/nvgrpc/options_test.go
- client-go/version/version_test.go
- .gitignore
- client-go/hack/boilerplate.go.txt
- client-go/nvgrpc/interceptors.go
- client-go/examples/basic-client/main.go
- client-go/nvgrpc/client_conn_test.go
- client-go/nvgrpc/client_conn.go
- client-go/nvgrpc/config.go
- client-go/nvgrpc/watcher_test.go
- client-go/nvgrpc/interceptors_test.go
- client-go/nvgrpc/options.go
- api/device/v1alpha1/gpu_conversion.go
- client-go/examples/streaming-daemon/README.md
- client-go/hack/overlays/client/versioned/clientset.go
- client-go/README.md
- client-go/examples/README.md
- client-go/examples/fake-server/README.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/version/version.goclient-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/examples/controller-shim/main.goclient-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/integration_test.goapi/device/v1alpha1/register.goapi/device/v1alpha1/gpu_types.goclient-go/nvgrpc/watcher.goclient-go/examples/fake-server/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goapi/device/v1alpha1/converter.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/integration_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
client-go/go.modapi/go.mod
🧠 Learnings (23)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
Makefile.gitattributes
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
Makefileclient-go/go.modapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
Makefileclient-go/go.modapi/go.modapi/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
Makefileclient-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/version/version.goclient-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/controller-shim/main.goapi/device/v1alpha1/gpu_types.goclient-go/nvgrpc/watcher.goclient-go/examples/fake-server/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/controller-shim/main.goclient-go/nvgrpc/watcher.goclient-go/examples/fake-server/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
.gitattributesclient-go/DEVELOPMENT.mdclient-go/go.modclient-go/examples/basic-client/README.mdclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goapi/go.modapi/Makefileclient-go/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/examples/streaming-daemon/main.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/watcher.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/go.modclient-go/nvgrpc/watcher.goapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/examples/controller-shim/main.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In Go tests across the repository, avoid introducing the testify dependency for simple equality/inequality checks. Use the standard testing package assertions (t.Error, t.Errorf, t.Fatal, etc.) for straightforward checks. Reserve third-party assertion libraries for complex scenarios that require richer diagnostics or expressive matchers.
Applied to files:
client-go/nvgrpc/config_test.goclient-go/hack/overlays/client/versioned/integration_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
client-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Aim for >80% test coverage on critical paths in Go code
Applied to files:
client-go/nvgrpc/config_test.go
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In the NVIDIA/NVSentinel repository, prefer not to introduce a dependency on `stretchr/testify` for simple comparison assertions in Go tests. Use standard `testing` package assertions (t.Error, t.Errorf, etc.) for straightforward checks.
Applied to files:
client-go/go.modapi/go.mod
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
🧬 Code graph analysis (9)
client-go/examples/streaming-daemon/main.go (6)
client-go/hack/overlays/client/versioned/clientset.go (2)
New(79-83)NewForConfigAndClient(48-65)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(58-63)NewForConfigAndClient(39-44)client-go/nvgrpc/config.go (3)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)Config(41-49)client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
client-go/hack/overlays/client/versioned/integration_test.go (4)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
api/device/v1alpha1/register.go (1)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
api/device/v1alpha1/gpu_types.go (1)
store-client/pkg/query/builder.go (1)
Condition(30-37)
client-go/examples/fake-server/main.go (3)
client-go/nvgrpc/config.go (2)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/gpu_conversion.go (1)
ToProto(35-40)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (4)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (2)
GPUsGetter(17-19)GPUInterface(22-27)client-go/hack/overlays/client/versioned/clientset.go (4)
NewForConfig(32-44)NewForConfigAndClient(48-65)NewForConfigOrDie(69-76)New(79-83)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(26-72)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (3)
GPU(55-61)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
🔇 Additional comments (41)
client-go/nvgrpc/config_test.go (3)
20-59: LGTM! Excellent precedence testing.The test thoroughly validates Target precedence (explicit argument → environment variable → default) using a clear table-driven approach and proper environment isolation via
t.Setenv.Based on learnings, standard library assertions are appropriate for these simple equality checks.
61-80: LGTM! UserAgent default behavior properly tested.Both subtests correctly validate UserAgent handling: default population when empty and preservation of custom values.
Based on learnings, standard library assertions are appropriate for these simple checks.
82-120: LGTM! Validation logic comprehensively tested.The test covers essential validation scenarios (valid config, missing target, missing user agent) with correct error assertion logic.
Based on learnings, standard library error assertions are appropriate here.
Makefile (1)
343-343: LGTM! Appropriate exclusion for generated overlay code.The ignore pattern for
**/hack/**aligns with the overlay-based code generation workflow introduced in this PR. This prevents the license header linter from flagging generated or overlay-driven content in hack directories.client-go/examples/basic-client/README.md (1)
1-38: Documentation is clear and well-structured.The README provides a solid reference implementation guide covering client initialization, K8s-native verbs, and metadata inspection. The instructions for running with and without root privileges are clear, and the expected output examples are helpful.
.gitattributes (1)
1-16: Excellent practice for managing generated code visibility.The linguist-generated attributes will significantly improve PR review experience by hiding auto-generated code (DeepCopy, Protobuf bindings, client libraries) from diffs. This aligns with the extensive code generation workflow introduced in this PR.
api/go.mod (1)
3-34: Dependency updates look appropriate.The Go version bump to 1.25.5 includes important security fixes. The addition of
google/go-cmpand the proper declaration ofk8s.io/apimachineryas a direct dependency align with the API module's use of Kubernetes types and testing utilities.client-go/go.mod (1)
1-74: Module dependencies are well-structured and version-aligned.The go.mod correctly establishes the client-go module with proper dependency versions. All Kubernetes modules are aligned to v0.34.1, and the inclusion of controller-runtime v0.22.4 enables advanced informer and cache patterns. The replace directive for the local API module is appropriate.
client-go/DEVELOPMENT.md (1)
1-105: Comprehensive and well-organized development guide.The DEVELOPMENT.md provides clear workflow instructions, prerequisites, and explains the code generation pipeline effectively. The mermaid diagram is particularly helpful for visualizing the multi-stage generation process. The warnings about not editing generated files directly are appropriately emphasized and will help prevent common mistakes.
client-go/hack/overlays/client/versioned/integration_test.go (2)
33-252: Comprehensive end-to-end test coverage.The test suite effectively validates the complete integration stack:
- gRPC transport layer with bufconn for in-process testing
- Standard K8s verbs (Get, List, Watch)
- Informer synchronization and cache updates
- Controller-runtime compatibility
The test structure is well-organized with clear subtests, appropriate timeouts, and good use of context cancellation.
256-335: Thread-safe mock server implementation.The mock GPU server correctly uses
sync.RWMutexto protect concurrent access to the GPU map. The channel-based event mechanism forWatchGpusis appropriate and the buffering (10 events) provides reasonable headroom for test scenarios.client-go/nvgrpc/watcher.go (3)
66-76: Proper idempotent shutdown implementation.The use of
sync.Onceensures thread-safe, idempotent shutdown. This correctly addresses the race condition that could occur with manual double-close protection.
138-170: Excellent error mapping for informer compatibility.The
sendErrorfunction correctly maps gRPC status codes to Kubernetes status codes. Particularly noteworthy is the mapping ofOutOfRange,ResourceExhausted, andInvalidArgumentto410 Expired(lines 147-150), which is critical for triggering informer re-list operations when the watch stream becomes stale.
84-136: Robust event loop with proper cleanup.The
receive()loop correctly handles:
- EOF and cancellation as normal shutdown conditions
- Event type mapping to Kubernetes watch.EventType
- Structured logging with appropriate verbosity levels
- Cleanup via deferred Stop() and result channel closure
The implementation follows best practices for context cancellation and proper shutdown handling.
Based on coding guidelines, proper shutdown handling with context cancellation is required in Go code.
client-go/version/version.go (1)
22-35: LGTM!The version variables and
UserAgent()function are well-documented and correctly implemented. The typo from the previous review has been fixed.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
14-23: LGTM!The
Next()method correctly receives from the stream, converts the protobuf object usingFromProto, and returns the event type with the converted object. Error handling is appropriate.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
17-24: LGTM!The
ClientConn()method is well-documented, clearly explaining that the fake implementation uses an ObjectTracker memory store rather than an actual gRPC connection. Returning nil is acceptable for a fake implementation.api/device/v1alpha1/register.go (1)
29-44: LGTM!The scheme registration follows standard Kubernetes API patterns.
SchemeBuilderandAddToSchemeare properly documented with inline comments, andaddKnownTypescorrectly registersGPUandGPUListtypes with the scheme.client-go/examples/streaming-daemon/main.go (3)
15-20: LGTM!Good package-level documentation that clearly explains the example's purpose as a long-running, event-driven agent with Watch stream and custom interceptors.
47-60: LGTM!The target resolution correctly uses the canonical constants from
nvgrpcand the tracing interceptor properly injects metadata into outgoing requests.
92-103: LGTM!Proper shutdown handling with
signal.NotifyContextfor graceful termination on SIGINT/SIGTERM. The List operation with error handling is correctly implemented.api/proto/device/v1alpha1/gpu.proto (2)
53-78: LGTM!The
GpuandGpuListmessages follow Kubernetes Resource Model patterns correctly. The metadata fields (ObjectMeta, ListMeta) enable proper resource versioning and watch semantics. The documentation clearly explains the resource naming convention.
152-167: LGTM!The
resource_versionfields inListGpusRequestandWatchGpusRequestenable clients to list/watch resources at a specific version, supporting proper List-then-Watch patterns and optimistic concurrency. Good documentation explains the purpose.client-go/examples/controller-shim/main.go (3)
15-20: LGTM!Good package-level documentation explaining the controller-shim pattern and how it bypasses the standard Kubernetes API server.
85-106: LGTM!The
NewInformerimplementation correctly:
- Injects the gRPC-backed informer for GPU objects
- Merges required indexers while avoiding conflicts
- Falls back to standard informers for non-GPU objects (previously raised issue addressed)
65-69: The SharedInformerFactory must be explicitly started or properly integrated with the manager.The code creates a
SharedInformerFactorywithout starting it. The comment claiming "the Manager will start the injected informer" is incorrect: if this factory is instantiated separately without being passed to a controller-runtime source or the manager's cache, it will not be started automatically. Either callfactory.Start(ctx)explicitly before using the informer, or integrate it with controller-runtime's cache viacache.Options.NewInformerso the manager handles its lifecycle.client-go/examples/fake-server/main.go (3)
15-20: LGTM!Good package-level documentation explaining the fake server's purpose for local testing and development.
135-169: LGTM!The
simulateChanges()implementation correctly:
- Uses proper mutex synchronization
- Increments
ResourceVersionon each update (K8s watch semantics)- Toggles Ready status and updates
LastTransitionTime- Makes a deep copy before broadcasting to avoid data races
210-260: LGTM!The
WatchGpusimplementation follows proper streaming patterns:
- Sends initial ADDED events for all GPUs
- Registers for updates via a buffered channel
- Properly cleans up the listener on disconnect
- Handles context cancellation gracefully
api/device/v1alpha1/gpu_types.go (1)
21-71: LGTM! Type definitions follow Kubernetes conventions.The GPU CRD type definitions are well-structured:
- Proper separation of Spec and Status
- Correct codegen markers for read-only, non-namespaced resources
- Clear field documentation with format examples
- Standard use of metav1 types
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
9-22: LGTM! Interface and client structure follow client-go patterns.The interface and struct definitions align with standard Kubernetes client-go conventions.
46-73: LGTM! Remaining constructors and accessor correctly implemented.The
NewForConfigOrDie,New, andClientConnmethods follow standard client-go patterns with appropriate nil-safety in the accessor.api/Makefile (3)
19-59: LGTM! Variable definitions are well-structured.The Makefile variables are properly defined with clear separation of concerns. The
API_PKGS_COMMAvariable (line 37) correctly addresses the previous review's concern.
86-142: LGTM! Code generation workflow is well-orchestrated.The Makefile targets implement a clean code-generation pipeline:
- Proper dependency chaining ensures generated code is up-to-date before build/test
- The
deepcopy-gentarget now correctly usesAPI_PKGS_COMMA(line 131)- Test exclusions appropriately skip generated code directories
169-205: LGTM! Tool installation logic is robust.The
go-install-toolmacro correctly:
- Maintains versioned binaries to avoid unnecessary re-downloads
- Propagates
GOTOOLCHAINto ensure consistent Go versions- Creates symlinks for convenient access
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
29-87: LGTM! Client implementation follows gRPC and client-go best practices.The GPU client implementation is well-structured:
- Proper proto-to-internal conversions using
FromProto/FromProtoList- Correct context cancellation handling in
Watchmethod- Appropriate logging verbosity levels for different operations
- Error propagation is clean and consistent
client-go/Makefile (3)
19-83: LGTM! Variable definitions are comprehensive and well-organized.The Makefile variables follow a consistent pattern with the API Makefile:
- Clear module and versioning metadata
- Proper string manipulation for code generation tools
- Centralized version management via
.versions.yaml- Appropriate linker flags for version injection
89-149: LGTM! Code generation workflow is properly orchestrated.The Makefile targets implement a well-designed multi-stage code generation pipeline:
- Dependency chain ensures correct build order (install-tools → client-gen → overlays → lister-gen → informer-gen)
- Test and build exclusions appropriately skip generated code and overlays
- Code generator arguments correctly reference cross-package dependencies
178-213: LGTM! Tool installation follows established patterns.The tool installation logic is consistent with the API Makefile and correctly handles versioned binaries with
GOTOOLCHAINpropagation.api/device/v1alpha1/converter.go (2)
106-133: LGTM! Helper functions are correctly implemented.The helper functions properly:
- Generate TypeMeta with full
group/versionAPIVersion format usingSchemeGroupVersion.String()(lines 110, 118) - addressing the previous review's concern- Handle nil timestamps safely in
FromProtobufTimestamp(lines 124-126)- Perform clean bidirectional timestamp conversions
23-104: LGTM! Converter interface is well-designed for code generation.The interface provides comprehensive bidirectional conversion methods with proper goverter annotations:
- Clear field mappings for name differences (e.g.,
Uuid↔UUID)- Appropriate ignore directives for protobuf internals
- Extension of helper functions for TypeMeta and timestamp conversions
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
Outdated
Show resolved
Hide resolved
d97ed84 to
8a0912d
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
3efcf77 to
cdb7585
Compare
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
Signed-off-by: Dan Huenecke <[email protected]>
cdb7585 to
cfd3179
Compare
There was a problem hiding this 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
♻️ Duplicate comments (14)
client-go/examples/basic-client/README.md (1)
20-38: Clarify expected output alignment with "Running without Root" instructions.The "Running without Root" section (line 24) overrides the socket to
unix:///tmp/device-api.sock, but the "Expected Output" section (line 31) shows the default socket pathunix:///var/run/nvidia-device-api/device-api.sock. This mismatch is confusing—it's unclear whether the expected output corresponds to the default case (withsudo) or the "without Root" variant.If the expected output is for the default case, restructure the documentation to make this explicit. If it's for the "without Root" case, update line 31 to reflect the overridden socket path.
🔎 Suggested clarification
Option A: Separate expected outputs for each case:
## Expected Output +### Running as Root + ```text -"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///var/run/nvidia-device-api/device-api.sock" +"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///var/run/nvidia-device-api/device-api.sock" "level"=0 "msg"="details" "name"="gpu-0" "uuid"="GPU-6e5b6a57..." ...+### Running without Root
+
+text +"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///tmp/device-api.sock" +"level"=0 "msg"="details" "name"="gpu-0" "uuid"="GPU-6e5b6a57..." +... +Option B: Update the single expected output to match the most recent instructions (line 24): ```diff -"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///var/run/nvidia-device-api/device-api.sock" +"level"=0 "msg"="discovered GPUs" "count"=8 "target"="unix:///tmp/device-api.sock"client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
25-27: CloseSend() is inappropriate for server-streaming RPCs.For server-streaming RPCs like
WatchGpus, the client only receives messages and does not send after the initial request. CallingCloseSend()is not the correct way to close a receive-only stream and may cause errors or fail to properly release resources. Either returnnildirectly or rely on context cancellation to properly close the stream.🔎 Suggested fix
func (a *gpuStreamAdapter) Close() error { - return a.stream.CloseSend() + return nil }Alternatively, if cleanup is needed, consider using
stream.Context().Done()to detect when the stream is closed by context cancellation.client-go/examples/fake-server/main.go (1)
195-208: Populate ListMeta with ResourceVersion.The
ListGpusresponse does not includeMetadata.ResourceVersion, which is needed for clients to establish a watch from a consistent point using the List-then-Watch pattern. Consider tracking a global resource version and populating it in the response.🔎 Suggested fix
func (s *fakeServer) ListGpus(ctx context.Context, req *pb.ListGpusRequest) (*pb.ListGpusResponse, error) { s.mu.RLock() defer s.mu.RUnlock() gpuList := &pb.GpuList{ + Metadata: &pb.ListMeta{ + ResourceVersion: "1", // Or compute max from s.gpus + }, Items: make([]*pb.Gpu, 0, len(s.gpus)), }client-go/version/version.go (1)
15-15: Add package-level godoc comment.Per coding guidelines, all Go packages require package-level documentation. Add a comment above the package declaration describing the purpose of the version package.
🔎 Suggested documentation
+// Package version provides build-time version information and user-agent +// string generation for the nvidia-device-api-client. package versionAs per coding guidelines, package-level godoc is required for all Go packages.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (2)
1-1: Add package-level godoc comment.The coding guidelines require package-level documentation for all Go packages. The fake package should have a comment describing its purpose.
As per coding guidelines, package-level godoc is required for all Go packages.
13-15: Add function comment for exported method.The GPUs() method is exported but lacks documentation. Add a comment describing what this method returns and its purpose in the fake client.
As per coding guidelines, function comments are required for all exported Go functions.
api/proto/device/v1alpha1/gpu.proto (1)
35-37: Fix indentation inconsistency.Lines 35-37 use tabs while surrounding comment lines use spaces. Normalize the indentation by replacing tabs with spaces to maintain consistency throughout the file.
client-go/examples/streaming-daemon/main.go (1)
146-148: Fix misleading log message.The log message says "context timeout reached" but the context is created from
signal.NotifyContext(line 93), which cancels on SIGINT/SIGTERM signals, not on timeout.🔎 Suggested fix
case <-ctx.Done(): - logger.Info("context timeout reached, stopping watch") + logger.Info("received shutdown signal, stopping watch") returnclient-go/hack/overlays/client/versioned/integration_test.go (1)
209-213: Avoid callingt.Errorffrom a goroutine.Calling
t.Errorffrom a goroutine is unsafe and can cause race conditions or panics if the test completes before the goroutine executes. Sincec.Start(ctx)blocks until context cancellation and typically only returns errors on shutdown, consider using an error channel or simply logging/ignoring the error.🔎 Suggested fix using error channel
+ errCh := make(chan error, 1) go func() { - if err := c.Start(ctx); err != nil { - t.Errorf("Cache failed to start: %v", err) - } + errCh <- c.Start(ctx) }() + + // Defer check for cache start errors (only relevant after test completes) + defer func() { + select { + case err := <-errCh: + if err != nil && ctx.Err() == nil { + t.Errorf("Cache failed to start: %v", err) + } + default: + } + }()client-go/examples/controller-shim/main.go (2)
135-152: Add godoc comments for exported methodsReconcileandSetupWithManager.Per coding guidelines, function comments are required for all exported Go functions.
Suggested additions
+// Reconcile retrieves the requested GPU resource from the gRPC-backed cache +// and logs its name and UUID. Returns without error if the GPU is not found. func (r *GPUReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := ctrl.LoggerFrom(ctx) var gpu devicev1alpha1.GPU // The Get call is transparently routed through the injected gRPC-backed informer. if err := r.Get(ctx, req.NamespacedName, &gpu); err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } log.Info("Reconciled GPU", "name", gpu.Name, "uuid", gpu.Spec.UUID) return ctrl.Result{}, nil } +// SetupWithManager registers the GPUReconciler with the provided manager, +// configuring it to watch GPU resources. func (r *GPUReconciler) SetupWithManager(mgr ctrl.Manager) error {
65-70: The gRPC-backed informer factory is never started.The comment on line 67 states the Manager will start the injected informer, but controller-runtime only starts informers created through its own cache machinery. The externally provided
gpuInformerfrom the gRPC factory must be started explicitly; otherwise, the cache will never populate.Suggested fix
factory := informers.NewSharedInformerFactory(clientset, 10*time.Minute) gpuInformer := factory.Device().V1alpha1().GPUs().Informer() + + // Start the informer factory before manager starts. + // Controller-runtime won't start externally-provided informers. + ctx := ctrl.SetupSignalHandler() + factory.Start(ctx.Done())Then move
ctx := ctrl.SetupSignalHandler()before the factory creation and remove the duplicate declaration at line 121.client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
1-1: Package-level documentation is still missing.As noted in the previous review, this package lacks the required package-level godoc comment.
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
1-1: Package-level documentation is still missing.As noted in the previous review, this package lacks the required package-level godoc comment.
client-go/Makefile (1)
187-187: Declare thetoolstarget as PHONY.As noted in the previous review and confirmed by static analysis, the
toolstarget should be declared.PHONYsince it doesn't produce a file output.
🧹 Nitpick comments (7)
client-go/nvgrpc/config_test.go (1)
82-120: LGTM with optional suggestion for completeness.The validation test correctly covers the essential scenarios: valid config, missing target, and missing user agent. The test logic is sound and follows the table-driven pattern appropriately.
Optional: Consider adding edge case test
For completeness, you could add a test case where both
TargetandUserAgentare empty:{ name: "Missing both target and user agent", cfg: Config{}, wantErr: true, },This would ensure full edge case coverage, though the current tests already validate the core validation logic.
api/go.mod (1)
11-17: Consider separating direct and indirect dependencies.While
k8s.io/apimachineryis now correctly declared as a direct dependency (past issue resolved), the current formatting mixes direct and indirect dependencies in the samerequireblock. For better clarity, consider movingk8s.io/apimachineryto the direct dependencies block at lines 5-9.🔎 Suggested reorganization
require ( github.com/google/go-cmp v0.7.0 google.golang.org/grpc v1.77.0 google.golang.org/protobuf v1.36.11 + k8s.io/apimachinery v0.34.1 ) require ( golang.org/x/net v0.47.0 // indirect golang.org/x/sys v0.38.0 // indirect golang.org/x/text v0.31.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251124214823-79d6a2a48846 // indirect - k8s.io/apimachinery v0.34.1 )After making this change, run
go mod tidyto ensure consistency.client-go/nvgrpc/client_conn.go (1)
15-15: Add package-level documentation.Per coding guidelines, package-level godoc is required for all Go packages. Consider adding documentation describing the purpose of the
nvgrpcpackage.🔎 Suggested documentation
+// Package nvgrpc provides gRPC client connectivity for the NVIDIA Device API, +// including connection configuration, transport credentials, keepalive settings, +// and observability interceptors. package nvgrpcclient-go/nvgrpc/interceptors_test.go (1)
30-42: Remove unusedexpectedCodefield from test struct.The
expectedCodefield is defined but never used in the test assertions. Either remove it or add an assertion that verifies the response code matches expectations.🔎 Proposed fix (remove unused field)
tests := []struct { name string method string log bool invokerErr error - expectedCode codes.Code }{ - {"Returns OK code for successful call", "/svc/success", true, nil, codes.OK}, - {"Returns internal status error on internal error", "/svc/internal_error", true, status.Error(codes.Internal, "fail"), codes.Internal}, - {"Returns canceled status error when canceled", "/svc/cancel", true, status.Error(codes.Canceled, ""), codes.Canceled}, - {"Returns deadline exceeded status error on timeout", "/svc/timeout", true, status.Error(codes.DeadlineExceeded, ""), codes.DeadlineExceeded}, - {"Does not log if logger disabled", "/svc/skip_log", false, nil, codes.OK}, + {"Returns OK code for successful call", "/svc/success", true, nil}, + {"Returns internal status error on internal error", "/svc/internal_error", true, status.Error(codes.Internal, "fail")}, + {"Returns canceled status error when canceled", "/svc/cancel", true, status.Error(codes.Canceled, "")}, + {"Returns deadline exceeded status error on timeout", "/svc/timeout", true, status.Error(codes.DeadlineExceeded, "")}, + {"Does not log if logger disabled", "/svc/skip_log", false, nil}, }client-go/examples/controller-shim/main.go (1)
130-133: Add godoc comment for the exportedGPUReconcilertype.Per coding guidelines, exported types should have documentation comments.
Suggested addition
+// GPUReconciler reconciles GPU resources using a gRPC-backed cache. +// It retrieves GPU state from the local NVIDIA Device API and logs reconciliation events. type GPUReconciler struct { client.Client }client-go/nvgrpc/interceptors.go (1)
57-85: Consider aligning verbosity levels between unary and stream interceptors.The unary interceptor logs success at
V(6)while the stream interceptor logs success atV(4). This inconsistency may confuse operators adjusting log verbosity. If intentional (e.g., streams are less frequent), consider adding a brief comment explaining the rationale.if err != nil || logger.V(4).Enabled() { + // Stream establishment is typically less frequent than unary RPCs, + // so we log at a lower verbosity level (V(4) vs V(6) for unary). s := status.Convert(err)client-go/hack/overlays/client/versioned/clientset.go (1)
1-10: Add copyright header to the overlay file.Other files in the PR include the NVIDIA Apache 2.0 copyright header. For consistency, this overlay should also include it.
Suggested addition
+// Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package versioned
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (28)
api/device/v1alpha1/zz_generated.conversion.gois excluded by!api/**/zz_generated.*api/device/v1alpha1/zz_generated.deepcopy.gois excluded by!api/**/zz_generated.*api/gen/go/device/v1alpha1/gpu.pb.gois excluded by!**/*.pb.go,!**/gen/**,!api/gen/**api/go.sumis excluded by!**/*.sumclient-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/fake/clientset_generated.gois excluded by!client-go/client/**client-go/client/versioned/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/fake/register.gois excluded by!client-go/client/**client-go/client/versioned/integration_test.gois excluded by!client-go/client/**client-go/client/versioned/scheme/doc.gois excluded by!client-go/client/**client-go/client/versioned/scheme/register.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/doc.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/fake/fake_gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/generated_expansion.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.gois excluded by!client-go/client/**client-go/go.sumis excluded by!**/*.sumclient-go/informers/externalversions/device/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/gpu.gois excluded by!client-go/informers/**client-go/informers/externalversions/device/v1alpha1/interface.gois excluded by!client-go/informers/**client-go/informers/externalversions/factory.gois excluded by!client-go/informers/**client-go/informers/externalversions/generic.gois excluded by!client-go/informers/**client-go/informers/externalversions/internalinterfaces/factory_interfaces.gois excluded by!client-go/informers/**client-go/listers/device/v1alpha1/expansion_generated.gois excluded by!client-go/listers/**client-go/listers/device/v1alpha1/gpu.gois excluded by!client-go/listers/**
📒 Files selected for processing (50)
.coderabbit.yaml.gitattributes.gitignore.versions.yamlMakefileapi/Makefileapi/device/v1alpha1/converter.goapi/device/v1alpha1/doc.goapi/device/v1alpha1/gpu_conversion.goapi/device/v1alpha1/gpu_conversion_test.goapi/device/v1alpha1/gpu_types.goapi/device/v1alpha1/register.goapi/go.modapi/hack/boilerplate.go.txtapi/proto/device/v1alpha1/gpu.protoclient-go/DEVELOPMENT.mdclient-go/Makefileclient-go/README.mdclient-go/examples/README.mdclient-go/examples/basic-client/README.mdclient-go/examples/basic-client/main.goclient-go/examples/controller-shim/README.mdclient-go/examples/controller-shim/main.goclient-go/examples/fake-server/README.mdclient-go/examples/fake-server/main.goclient-go/examples/streaming-daemon/README.mdclient-go/examples/streaming-daemon/main.goclient-go/go.modclient-go/hack/apply-overlays.shclient-go/hack/boilerplate.go.txtclient-go/hack/boilerplate_overlay.go.txtclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/nvgrpc/client_conn.goclient-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/config.goclient-go/nvgrpc/config_test.goclient-go/nvgrpc/doc.goclient-go/nvgrpc/interceptors.goclient-go/nvgrpc/interceptors_test.goclient-go/nvgrpc/options.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/watcher.goclient-go/nvgrpc/watcher_test.goclient-go/version/version.goclient-go/version/version_test.go
✅ Files skipped from review due to trivial changes (1)
- client-go/nvgrpc/doc.go
🚧 Files skipped from review as they are similar to previous changes (18)
- .versions.yaml
- client-go/examples/streaming-daemon/README.md
- .gitignore
- client-go/version/version_test.go
- api/hack/boilerplate.go.txt
- api/device/v1alpha1/doc.go
- client-go/nvgrpc/config.go
- client-go/nvgrpc/watcher.go
- api/device/v1alpha1/register.go
- Makefile
- api/device/v1alpha1/gpu_conversion_test.go
- client-go/examples/README.md
- .coderabbit.yaml
- client-go/hack/apply-overlays.sh
- client-go/examples/fake-server/README.md
- client-go/hack/boilerplate_overlay.go.txt
- client-go/nvgrpc/watcher_test.go
- client-go/examples/controller-shim/README.md
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
client-go/nvgrpc/client_conn_test.goclient-go/examples/basic-client/main.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/interceptors_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/examples/controller-shim/main.goapi/device/v1alpha1/gpu_types.goclient-go/nvgrpc/config_test.goapi/device/v1alpha1/converter.goclient-go/nvgrpc/interceptors.goapi/device/v1alpha1/gpu_conversion.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/nvgrpc/options.goclient-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/nvgrpc/client_conn.goclient-go/examples/streaming-daemon/main.goclient-go/examples/fake-server/main.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
client-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/interceptors_test.goclient-go/nvgrpc/config_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
client-go/go.modapi/go.mod
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go:15-27
Timestamp: 2025-12-22T16:48:09.264Z
Learning: In the client-go module, files under `hack/overlays/` use the overlay pattern: they are copied into generated code directories and are not compiled standalone. These overlay files may reference types (e.g., `GPUExpansion`) that are generated by Kubernetes code-gen tools and only exist in the final destination. The build excludes overlays via grep patterns like `grep -vE '/hack/overlays/|/examples/'`. Do not flag missing type references in overlay files as compilation errors.
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In Go tests across the repository, avoid introducing the testify dependency for simple equality/inequality checks. Use the standard testing package assertions (t.Error, t.Errorf, t.Fatal, etc.) for straightforward checks. Reserve third-party assertion libraries for complex scenarios that require richer diagnostics or expressive matchers.
Applied to files:
client-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/nvgrpc/interceptors_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
client-go/nvgrpc/client_conn_test.goclient-go/go.modclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
client-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
client-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
client-go/nvgrpc/client_conn_test.go.gitattributesclient-go/examples/basic-client/main.goclient-go/go.modclient-go/README.mdclient-go/examples/basic-client/README.mdclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/Makefileclient-go/version/version.goapi/go.modclient-go/DEVELOPMENT.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Aim for >80% test coverage on critical paths in Go code
Applied to files:
client-go/nvgrpc/client_conn_test.goclient-go/nvgrpc/options_test.goclient-go/nvgrpc/config_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : TODO comments should reference issues in Go code
Applied to files:
client-go/nvgrpc/client_conn_test.goclient-go/go.modclient-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/nvgrpc/options.goclient-go/version/version.go
📚 Learning: 2025-12-22T16:48:09.264Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go:15-27
Timestamp: 2025-12-22T16:48:09.264Z
Learning: In the client-go module, files under `hack/overlays/` use the overlay pattern: they are copied into generated code directories and are not compiled standalone. These overlay files may reference types (e.g., `GPUExpansion`) that are generated by Kubernetes code-gen tools and only exist in the final destination. The build excludes overlays via grep patterns like `grep -vE '/hack/overlays/|/examples/'`. Do not flag missing type references in overlay files as compilation errors.
Applied to files:
.gitattributesclient-go/go.modclient-go/README.mdclient-go/hack/boilerplate.go.txtapi/device/v1alpha1/gpu_conversion.goclient-go/nvgrpc/options.goclient-go/Makefileapi/Makefileclient-go/DEVELOPMENT.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.gitattributes
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
client-go/go.modclient-go/Makefileapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
client-go/go.modapi/Makefileapi/go.mod
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In the NVIDIA/NVSentinel repository, prefer not to introduce a dependency on `stretchr/testify` for simple comparison assertions in Go tests. Use standard `testing` package assertions (t.Error, t.Errorf, etc.) for straightforward checks.
Applied to files:
client-go/go.modclient-go/hack/boilerplate.go.txtapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/go.modclient-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/controller-shim/main.goapi/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Use `commons/` for shared utilities across Go modules
Applied to files:
client-go/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/nvgrpc/options_test.goclient-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
client-go/hack/boilerplate.go.txt
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/examples/streaming-daemon/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/examples/controller-shim/main.go
📚 Learning: 2025-12-22T16:48:09.264Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go:15-27
Timestamp: 2025-12-22T16:48:09.264Z
Learning: In the client-go module, treat files under client-go/hack/overlays/ as overlay-generated code: they are copied into generated code directories and are not compiled standalone. Do not treat missing type references (e.g., generated by Kubernetes code-gen tools) in overlay files as compilation errors. Build excludes overlays with patterns like grep -vE '/hack/overlays/|/examples/'. Apply this guideline to all files under client-go/hack/overlays/.
Applied to files:
client-go/hack/overlays/client/versioned/integration_test.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/hack/overlays/client/versioned/clientset.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Function comments required for all exported Go functions
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/controller-shim/main.goclient-go/nvgrpc/options.goclient-go/version/version.goclient-go/examples/fake-server/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Package-level godoc required for all Go packages
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.goclient-go/examples/controller-shim/main.goapi/device/v1alpha1/gpu_types.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.goclient-go/version/version.goclient-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.goclient-go/examples/streaming-daemon/main.goclient-go/examples/fake-server/main.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Include comprehensive comments for all fields in Protocol Buffer messages
Applied to files:
api/device/v1alpha1/converter.goapi/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-12-01T17:53:20.067Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 455
File: docs/designs/013-remediation-plugins.md:162-204
Timestamp: 2025-12-01T17:53:20.067Z
Learning: Code examples in design documents (docs/designs/) in the NVSentinel repository are illustrative stubs meant to show intent and architectural concepts, and do not need to be 100% correct or complete implementations (e.g., undefined variables, missing error handling, incomplete struct initialization are acceptable).
Applied to files:
api/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Use semantic versioning for breaking changes in Protocol Buffer messages
Applied to files:
api/proto/device/v1alpha1/gpu.proto
📚 Learning: 2025-11-04T06:31:02.147Z
Learnt from: Gyan172004
Repo: NVIDIA/NVSentinel PR: 223
File: platform-connectors/pkg/nodemetadata/processor.go:0-0
Timestamp: 2025-11-04T06:31:02.147Z
Learning: In platform-connectors/pkg/nodemetadata/processor.go, the NewProcessor function does not perform a nil check on the config parameter because the caller is expected to guarantee a non-nil config is provided.
Applied to files:
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go
🧬 Code graph analysis (14)
client-go/nvgrpc/client_conn_test.go (4)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(39-87)client-go/version/version.go (1)
UserAgent(28-35)client-go/nvgrpc/options.go (1)
WithLogger(32-36)
client-go/examples/basic-client/main.go (3)
client-go/hack/overlays/client/versioned/clientset.go (2)
New(79-83)NewForConfig(32-44)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
New(71-76)NewForConfig(29-41)client-go/nvgrpc/config.go (3)
NvidiaDeviceAPITargetEnvVar(28-28)DefaultNvidiaDeviceAPISocket(31-31)Config(41-49)
client-go/nvgrpc/options_test.go (1)
client-go/nvgrpc/options.go (4)
DialOption(23-23)WithLogger(32-36)WithUnaryInterceptor(39-43)WithStreamInterceptor(46-50)
client-go/hack/overlays/client/versioned/integration_test.go (5)
client-go/nvgrpc/config.go (1)
Config(41-49)client-go/hack/overlays/client/versioned/clientset.go (2)
NewForConfigAndClient(48-65)New(79-83)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (2)
NewForConfigAndClient(45-57)New(71-76)api/device/v1alpha1/gpu_types.go (1)
GPU(55-61)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
client-go/nvgrpc/interceptors_test.go (1)
client-go/nvgrpc/interceptors.go (2)
NewErrorLoggingUnaryInterceptor(27-55)NewErrorLoggingStreamInterceptor(58-85)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu_stream_adapter.go (1)
api/device/v1alpha1/gpu_conversion.go (1)
FromProto(25-32)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/fake/fake_device_client.go (1)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (1)
GPUInterface(22-27)
client-go/hack/overlays/client/versioned/clientset.go (3)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (6)
DeviceV1alpha1Interface(11-14)DeviceV1alpha1Client(17-20)NewForConfig(29-41)NewForConfigAndClient(45-57)NewForConfigOrDie(61-68)New(71-76)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(39-87)
client-go/nvgrpc/config_test.go (2)
client-go/nvgrpc/config.go (3)
DefaultNvidiaDeviceAPISocket(31-31)NvidiaDeviceAPITargetEnvVar(28-28)Config(41-49)client-go/version/version.go (1)
UserAgent(28-35)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
api/device/v1alpha1/gpu_conversion.go (2)
api/device/v1alpha1/converter.go (1)
Converter(30-104)api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (5)
api/device/v1alpha1/gpu_types.go (2)
GPU(55-61)GPUList(67-71)client-go/hack/overlays/client/versioned/clientset.go (1)
Interface(12-14)client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (1)
DeviceV1alpha1Client(17-20)api/device/v1alpha1/gpu_conversion.go (2)
FromProto(25-32)FromProtoList(43-48)client-go/nvgrpc/watcher.go (1)
NewWatcher(49-64)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/device_client.go (4)
client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go (2)
GPUsGetter(17-19)GPUInterface(22-27)client-go/hack/overlays/client/versioned/clientset.go (4)
NewForConfig(32-44)NewForConfigAndClient(48-65)NewForConfigOrDie(69-76)New(79-83)client-go/nvgrpc/config.go (1)
Config(41-49)client-go/nvgrpc/client_conn.go (1)
ClientConnFor(39-87)
client-go/nvgrpc/client_conn.go (4)
client-go/nvgrpc/config.go (3)
Config(41-49)DefaultKeepAliveTime(34-34)DefaultKeepAliveTimeout(37-37)client-go/nvgrpc/options.go (1)
DialOption(23-23)client-go/version/version.go (1)
UserAgent(28-35)client-go/nvgrpc/interceptors.go (2)
NewErrorLoggingUnaryInterceptor(27-55)NewErrorLoggingStreamInterceptor(58-85)
🪛 checkmake (0.2.2)
client-go/Makefile
[warning] 187-187: Target "tools" should be declared PHONY.
(phonydeclared)
Signed-off-by: Dan Huenecke <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🤖 Fix all issues with AI agents
In @.versions.yaml:
- Around line 49-50: The .versions.yaml entry for goverter is incorrect—update
the goverter key value from 'v1.9.3' to the existing release 'v1.9.2' while
leaving kubernetes_code_gen at 'v0.34.1' unchanged; locate the goverter entry in
the file and replace its version string so the key "goverter" reads 'v1.9.2'.
In @client-go/DEVELOPMENT.md:
- Line 13: Fix the typo in DEVELOPMENT.md by updating the description for the
`version/` entry: replace "fFunctionality" with "Functionality" so the line
reads "`version/`: [Manual] Version injection Functionality via `ldflags`."
In @client-go/examples/streaming-daemon/README.md:
- Around line 19-21: Change the phrasing in the README note to tighten wording:
replace “the exact same URI” with “the same URI” in the sentence that tells
users to override the socket path with the NVIDIA_DEVICE_API_TARGET environment
variable so it reads “…override the socket path with the
NVIDIA_DEVICE_API_TARGET environment variable to the same URI here.” to improve
readability.
In @client-go/tests/integration/device/v1alpha1/clientset_test.go:
- Line 1: This file is missing the required Apache 2.0 license header; add the
standard Apache 2.0 license comment block at the top of the file above the
package declaration in
client-go/tests/integration/device/v1alpha1/clientset_test.go, then run the
repository's license linter (make license-headers-lint) to ensure formatting and
compliance.
In @code-generator/cmd/client-gen/args/gvpackages.go:
- Around line 44-50: NewInputBasePathValue calls v.Set(def) and ignores its
returned error which can hide builder.update() failures; update the constructor
to check the error returned by inputBasePathValue.Set(def) and panic on non-nil
error (consistent with NewGVPackagesValue/NewGVTypesValue) so invalid default
values fail fast—locate NewInputBasePathValue and inputBasePathValue.Set (which
calls builder.update()) and change the call to capture err and panic with a
descriptive message if err != nil.
In @code-generator/cmd/client-gen/generators/client_generator.go:
- Around line 334-355: sanitizePackagePaths assumes context.FindPackages(input)
returns a non-empty slice and dereferences pkgs[0], which can panic if the slice
is empty; after calling context.FindPackages(input) in sanitizePackagePaths,
check if len(pkgs) == 0 and return a descriptive error (e.g., "no packages found
for input %q") before accessing pkgs[0], ensuring ver.Package is only set when a
package is actually available.
- Around line 304-326: The loop in applyGroupOverrides uses
gvs.Versions[0].Version without checking that gvs.Versions is non-empty, which
can panic; update the loop that builds newGroups so it first verifies
len(gvs.Versions) > 0 (or skips/returns an error for empty Versions) before
accessing Versions[0], and handle empty cases by either continuing with gvs
unchanged, setting a safe default version, or returning a clear error; adjust
references in this block that create clientgentypes.GroupVersion and
clientgentypes.GroupVersions to use the validated version value or the chosen
fallback.
In @code-generator/cmd/client-gen/generators/util/tags.go:
- Around line 157-186: The HasVerb method currently ignores the Tags.NoVerbs
flag so +genclient:noVerbs is ineffective; modify Tags.HasVerb to first check if
t.NoVerbs is true and immediately return false for any verb, otherwise preserve
the existing SkipVerbs logic (iterate t.SkipVerbs and return false if verb
matches, true otherwise). Update the Tags.HasVerb implementation to reference
the NoVerbs field before consulting SkipVerbs so generators honor
+genclient:noVerbs.
- Around line 145-155: The Input() and Result() methods currently return (type,
package) but their comments say they should return (package path, type); fix
both by swapping the return values so they return
strings.Join(parts[0:len(parts)-1], ".") first (the package path) and
parts[len(parts)-1] second (the type); do this for extension.Input() and
extension.Result() while preserving the current split logic and single-segment
behavior.
- Around line 223-250: The conflict logic currently overwrites ret.SkipVerbs
when onlyVerbs is specified and never compares the user-provided skip list,
causing silent drops; update the block handling genClientPrefix+"onlyVerbs" so
it first collects onlyVerbs (appending v[0] if present), then check for any
intersection between the existing ret.SkipVerbs (from
genClientPrefix+"skipVerbs") and onlyVerbs and return an error if any verb
appears in both, and only if no conflict compute the new skip list from
SupportedVerbs (or keep the original ret.SkipVerbs when onlyVerbs is empty);
ensure you reference and preserve ret.SkipVerbs, onlyVerbs, SupportedVerbs and
the genClientPrefix+"skipVerbs"/+"onlyVerbs" values during these checks.
In @code-generator/cmd/client-gen/types/helpers.go:
- Around line 84-91: defaultVersion can panic when called with an empty versions
slice because it indexes versionStrings[len(versionStrings)-1]; add a defensive
check in defaultVersion to return a sensible zero value or an error when
len(versions)==0 (for example return Version("") or a defined default) and
document the precondition; ensure you still build the sorted slice using
sortableSliceOfVersions(versionStrings) and reference the
PackageVersion.Version.String() mapping unchanged, and update any callers or add
tests to assert behavior when versions is empty so callers handle the empty-case
consistently.
🧹 Nitpick comments (19)
client-go/examples/README.md (1)
31-31: Simplify the phrase "exact same URI" to reduce wordiness.The phrase "to the exact same URI here" can be shortened to "to the same URI here" or "to that URI here" for conciseness.
✏️ Proposed wording improvement
-If you started the server with a non-default target, override the socket path with the `NVIDIA_DEVICE_API_TARGET` environment variable to the exact same URI here. +If you started the server with a non-default target, override the socket path with the `NVIDIA_DEVICE_API_TARGET` environment variable to the same URI here.client-go/examples/basic-client/README.md (1)
16-16: Simplify the phrase "exact same URI" to reduce wordiness.The phrase "to the exact same URI here" can be shortened to "to the same URI here" or "to that URI here" for conciseness.
✏️ Proposed wording improvement
-If you started the server with a non-default target, override the socket path with the `NVIDIA_DEVICE_API_TARGET` environment variable to the exact same URI here. +If you started the server with a non-default target, override the socket path with the `NVIDIA_DEVICE_API_TARGET` environment variable to the same URI here.api/DEVELOPMENT.md (1)
7-7: Optional: Fix list indentation.Markdown linting flags the indentation at line 7 (expected 2 spaces, actual 4).
📝 Proposed formatting fix
- - All Go type definitions must strictly follow the standard [Kubernetes Resource Model](https://github.com/kubernetes/design-proposals-archive/blob/main/architecture/resource-management.md). + - All Go type definitions must strictly follow the standard [Kubernetes Resource Model](https://github.com/kubernetes/design-proposals-archive/blob/main/architecture/resource-management.md).client-go/examples/controller-shim/README.md (1)
9-9: Optional: Fix list indentation.Markdown linting flags the indentation at line 9 (expected 2 spaces, actual 4).
📝 Proposed formatting fix
- - _TIP_: Review the `NewInformer` setup in `main.go`. This is the "magic" that allows the standard `controller-runtime` machinery to work over gRPC/UDS without modifying the core controller logic. + - _TIP_: Review the `NewInformer` setup in `main.go`. This is the "magic" that allows the standard `controller-runtime` machinery to work over gRPC/UDS without modifying the core controller logic.code-generator/cmd/client-gen/README.md (1)
47-60: Optional: Add blank lines around the table.Markdown linting requires blank lines before and after tables for proper rendering.
📝 Proposed formatting fix
## Flags + | Flag | Required | Description | |------|----------|-------------|code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go (1)
24-60: Add package-level godoc + consider import-alias deconfliction
- New
schemepackage has no// Package scheme ...doc comment (and exported methods likeNamers/Imports/GenerateTypeare also undocumented). As per coding guidelines, this will trip lint in many setups.groupAlias := strings.ToLower(g.GroupGoNames[...])risks alias collisions if two groups share the samegroupGoName(esp. with overrides). Consider deconflicting (e.g., include version or group package name) or add a validation step up-front.Proposed minimal doc fix
@@ package scheme + +// Package scheme contains generators for emitting scheme/codec registration +// for generated clientsets.Also applies to: 68-89
code-generator/cmd/client-gen/generators/generator_for_type.go (1)
324-341: Use singular parameter names for Create/Update/UpdateStatus templatesThese signatures currently use
$.type|allLowercasePlural$ *$.type|raw$(e.g.,gpus *GPU), which is confusing for a single object and makes generated code harder to read.Proposed fix
@@ var createTemplate = ` func (c *$.type|allLowercasePlural$) Create(ctx $.context|raw$, $.type|allLowercasePlural$ *$.type|raw$, opts $.CreateOptions|raw$) (*$.type|raw$, error) { return nil, $.fmtErrorf|raw$("Create not implemented for gRPC transport") } ` @@ var updateTemplate = ` func (c *$.type|allLowercasePlural$) Update(ctx $.context|raw$, $.type|allLowercasePlural$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) { return nil, $.fmtErrorf|raw$("Update not implemented for gRPC transport") } ` @@ var updateStatusTemplate = ` func (c *$.type|allLowercasePlural$) UpdateStatus(ctx $.context|raw$, $.type|allLowercasePlural$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) { return nil, $.fmtErrorf|raw$("UpdateStatus not implemented for gRPC transport") } `@@ var createTemplate = ` -func (c *$.type|allLowercasePlural$) Create(ctx $.context|raw$, $.type|allLowercasePlural$ *$.type|raw$, opts $.CreateOptions|raw$) (*$.type|raw$, error) { +func (c *$.type|allLowercasePlural$) Create(ctx $.context|raw$, obj *$.type|raw$, opts $.CreateOptions|raw$) (*$.type|raw$, error) { return nil, $.fmtErrorf|raw$("Create not implemented for gRPC transport") } ` @@ var updateTemplate = ` -func (c *$.type|allLowercasePlural$) Update(ctx $.context|raw$, $.type|allLowercasePlural$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) { +func (c *$.type|allLowercasePlural$) Update(ctx $.context|raw$, obj *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) { return nil, $.fmtErrorf|raw$("Update not implemented for gRPC transport") } ` @@ var updateStatusTemplate = ` -func (c *$.type|allLowercasePlural$) UpdateStatus(ctx $.context|raw$, $.type|allLowercasePlural$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) { +func (c *$.type|allLowercasePlural$) UpdateStatus(ctx $.context|raw$, obj *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) { return nil, $.fmtErrorf|raw$("UpdateStatus not implemented for gRPC transport") } `api/device/v1alpha1/converter.go (1)
130-133: Consider returningnilfor zerometav1.Timeto preserve “unset” semanticsIf protobuf timestamp fields are optional, emitting a concrete timestamp for zero-valued
metav1.Time{}can turn “missing” into “set to year 1”. If callers rely on “unset”, consider mapping zero tonil.Proposed fix
@@ func ToProtobufTimestamp(source metav1.Time) *timestamppb.Timestamp { + if source.IsZero() { + return nil + } return timestamppb.New(source.Time) }client-go/tests/integration/device/v1alpha1/clientset_test.go (3)
122-122: Add type assertion safety check.The type assertion
event.Object.(*devicev1alpha1.GPU)can panic if the object is not a GPU. Use the two-value form to handle unexpected types gracefully.♻️ Proposed fix
- gpu := event.Object.(*devicev1alpha1.GPU) + gpu, ok := event.Object.(*devicev1alpha1.GPU) + if !ok { + t.Fatalf("Expected GPU object, got %T", event.Object) + }
209-213: Consider blocking on cache start errors.The cache is started in a goroutine with errors reported via
t.Errorf, which won't immediately fail the test. If the cache fails to start, subsequent assertions may produce misleading failures. Consider using a channel or other mechanism to propagate startup errors synchronously, or at minimum uset.Fatalfif startup is critical for the test.
298-316: Refactor lock scope in WatchGpus to prevent potential deadlock.The
RLockis held while iterating and sending tostream.Send()(lines 302-315), which can block if the stream is slow. This creates potential for deadlock or long lock hold times. Consider collecting the snapshot into a slice first, then releasing the lock before sending.♻️ Proposed fix
func (m *mockGpuServer) WatchGpus(req *pb.WatchGpusRequest, stream pb.GpuService_WatchGpusServer) error { m.mu.RLock() - // Send the initial snapshot (Current state) + // Collect the initial snapshot + snapshot := make([]*pb.Gpu, 0, len(m.gpus)) for _, g := range m.gpus { + snapshot = append(snapshot, g) + } + m.mu.RUnlock() + + // Send the initial snapshot (Current state) + for _, g := range snapshot { select { case <-stream.Context().Done(): - m.mu.RUnlock() return nil default: if err := stream.Send(&pb.WatchGpusResponse{ Type: "ADDED", Object: g, }); err != nil { - m.mu.RUnlock() return err } } } - m.mu.RUnlock() // Continuous watch (Live events)api/README.md (1)
7-7: Fix markdown list indentation.The nested list item has 4 spaces of indentation but should have 2 per markdown conventions.
♻️ Proposed fix
* **`proto/`**: Contains the **Protobuf Message and gRPC Service Definitions**. - * *Note:* The `ObjectMeta` and `ListMeta` messages are subsets of `k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta` and `k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta` respectively. + * *Note:* The `ObjectMeta` and `ListMeta` messages are subsets of `k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta` and `k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta` respectively.code-generator/cmd/client-gen/args/gvpackages_test.go (1)
37-123: LGTM! Comprehensive table-driven test.The test provides good coverage of GV package flag parsing scenarios including empty inputs, multiple groups, defaults, API paths, and import base paths. The use of the standard
testingpackage aligns with project conventions, and the table-driven structure makes it easy to add new test cases.💡 Optional: Consider more descriptive test naming
While the current name is acceptable, following the pattern
TestFunctionName_Scenario_ExpectedBehaviormore strictly could improve readability. For example:-func TestGVPackageFlag(t *testing.T) { +func TestGVPackageFlag_VariousInputs_ParsesCorrectly(t *testing.T) {As per coding guidelines for test naming.
code-generator/cmd/client-gen/args/gvtype.go (1)
66-71: Variabletypesshadows the imported package.The variable
typeson line 66 shadows the imported packagegithub.com/nvidia/nvsentinel/code-generator/cmd/client-gen/types. While this works because the package isn't used after this point in the function, it can cause confusion and potential bugs if the function is modified later.Suggested rename
- types, ok := (*s.gvToTypes)[gv] + typesList, ok := (*s.gvToTypes)[gv] if !ok { - types = []string{} + typesList = []string{} } - types = append(types, typeStr) - (*s.gvToTypes)[gv] = types + typesList = append(typesList, typeStr) + (*s.gvToTypes)[gv] = typesListcode-generator/cmd/client-gen/types/helpers.go (2)
58-79: Consider compiling regex at package level for performance.The regex
regexp.MustCompile("^[0-9]+")is compiled insideLess(), which is called O(n log n) times during sorting. For large version lists, this could be inefficient.However, since this is copied unmodified from upstream Kubernetes code-generator for compatibility, this may be intentional. Consider adding a comment noting this is kept for upstream parity.
124-127: Remove or document commented-out code.The commented-out
NormalizeGroupVersionfunction appears to be dead code. Consider removing it or adding a comment explaining why it's preserved.api/Makefile (1)
27-28: Redundantcode-genexecution inalltarget.The
alltarget explicitly depends oncode-gen, but bothtestandbuildalso depend oncode-gen. This causescode-gento be evaluated multiple times when runningmake all.Consider either:
- Removing
code-genfromallsince it's implicitly run viatestandbuild, or- Removing
code-genas a dependency fromtestandbuildifallis the primary entry point.Option 1: Simplify `all` target
-.PHONY: all -all: code-gen test build ## Run code generation, compile all code, and execute tests. +.PHONY: all +all: test build ## Run code generation, compile all code, and execute tests.code-generator/cmd/client-gen/generators/generator_for_group.go (1)
218-226: Consider documenting the Discard logger behavior.The
Newfunction creates a client with a discarded logger, which silently drops all log messages. While this is a reasonable default for simple use cases, callers may not realize logging is disabled.Consider adding a comment to the template noting this behavior, or providing an alternative constructor that accepts a logger parameter.
📝 Suggested documentation improvement
var newClientForGrpcConnTemplate = ` // New creates a new $.GroupGoName$$.Version$Client for the given gRPC client connection. +// Note: This constructor uses a no-op logger. For logging support, use NewForConfigAndClient instead. func New(c $.ClientConnInterface|raw$) *$.GroupGoName$$.Version$Client { return &$.GroupGoName$$.Version$Client{ conn: c, logger: $.Discard|raw$(), } } `code-generator/kube_codegen.sh (1)
645-653: Debug echo statements should be removed or made conditional.Lines 647 and 652 contain debug echo statements (
echo "input_pkgs=${input_pkgs}"andecho "group_versions=${group_versions}") that will output to stdout during code generation.These should either be removed for production use or made conditional on a verbose flag.
♻️ Suggested fix
if grep -E -q '^v[0-9]+((alpha|beta)[0-9]+)?$' <<< "${leaf}"; then input_pkgs+=("${pkg}") - echo "input_pkgs=${input_pkgs}" + if [ "${v}" -ge 2 ]; then + echo "input_pkgs=${input_pkgs[@]}" + fi dir2="$(dirname "${dir}")" leaf2="$(basename "${dir2}")" group_versions+=("${leaf2}/${leaf}") - echo "group_versions=${group_versions}" + if [ "${v}" -ge 2 ]; then + echo "group_versions=${group_versions[@]}" + fi fi
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
api/device/v1alpha1/zz_generated.goverter.gois excluded by!api/**/zz_generated.*client-go/client/versioned/clientset.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/device_client.gois excluded by!client-go/client/**client-go/client/versioned/typed/device/v1alpha1/gpu.gois excluded by!client-go/client/**code-generator/go.sumis excluded by!**/*.sum
📒 Files selected for processing (39)
.versions.yamlapi/DEVELOPMENT.mdapi/Makefileapi/README.mdapi/device/v1alpha1/converter.goapi/hack/update-codegen.shclient-go/DEVELOPMENT.mdclient-go/Makefileclient-go/README.mdclient-go/examples/README.mdclient-go/examples/basic-client/README.mdclient-go/examples/controller-shim/README.mdclient-go/examples/streaming-daemon/README.mdclient-go/go.modclient-go/hack/update-codegen.shclient-go/tests/integration/device/v1alpha1/clientset_test.gocode-generator/CONFIGURATION.mdcode-generator/LICENSEcode-generator/README.mdcode-generator/cmd/client-gen/README.mdcode-generator/cmd/client-gen/args/args.gocode-generator/cmd/client-gen/args/gvpackages.gocode-generator/cmd/client-gen/args/gvpackages_test.gocode-generator/cmd/client-gen/args/gvtype.gocode-generator/cmd/client-gen/generators/client_generator.gocode-generator/cmd/client-gen/generators/generator_for_clientset.gocode-generator/cmd/client-gen/generators/generator_for_expansion.gocode-generator/cmd/client-gen/generators/generator_for_group.gocode-generator/cmd/client-gen/generators/generator_for_type.gocode-generator/cmd/client-gen/generators/scheme/generator_for_scheme.gocode-generator/cmd/client-gen/generators/util/gvpackages.gocode-generator/cmd/client-gen/generators/util/tags.gocode-generator/cmd/client-gen/generators/util/tags_test.gocode-generator/cmd/client-gen/main.gocode-generator/cmd/client-gen/types/helpers.gocode-generator/cmd/client-gen/types/helpers_test.gocode-generator/cmd/client-gen/types/types.gocode-generator/go.modcode-generator/kube_codegen.sh
✅ Files skipped from review due to trivial changes (2)
- code-generator/CONFIGURATION.md
- code-generator/README.md
🚧 Files skipped from review as they are similar to previous changes (3)
- client-go/README.md
- client-go/go.mod
- client-go/Makefile
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.go: Follow standard Go conventions with gofmt and golint
Use structured logging vialog/slogin Go code
Wrap errors with context usingfmt.Errorf("context: %w", err)in Go code
Withinretry.RetryOnConflictblocks, return errors without wrapping to preserve retry behavior
Use meaningful variable names such assyncedoverokfor cache sync checks
Useclient-gofor Kubernetes API interactions in Go code
Prefer informers over direct API calls for watching Kubernetes resources
Implement proper shutdown handling with context cancellation in Go code
Package-level godoc required for all Go packages
Function comments required for all exported Go functions
Use inline comments for complex logic only in Go code
TODO comments should reference issues in Go code
Extract informer event handler setup into helper methods
Use separate informers for different Kubernetes resource types
Files:
code-generator/cmd/client-gen/generators/util/gvpackages.gocode-generator/cmd/client-gen/types/helpers_test.gocode-generator/cmd/client-gen/args/args.gocode-generator/cmd/client-gen/args/gvpackages_test.gocode-generator/cmd/client-gen/generators/generator_for_group.gocode-generator/cmd/client-gen/types/helpers.gocode-generator/cmd/client-gen/types/types.gocode-generator/cmd/client-gen/generators/client_generator.gocode-generator/cmd/client-gen/generators/scheme/generator_for_scheme.goclient-go/tests/integration/device/v1alpha1/clientset_test.gocode-generator/cmd/client-gen/args/gvtype.goapi/device/v1alpha1/converter.gocode-generator/cmd/client-gen/generators/util/tags.gocode-generator/cmd/client-gen/generators/generator_for_type.gocode-generator/cmd/client-gen/args/gvpackages.gocode-generator/cmd/client-gen/generators/generator_for_clientset.gocode-generator/cmd/client-gen/generators/util/tags_test.gocode-generator/cmd/client-gen/generators/generator_for_expansion.gocode-generator/cmd/client-gen/main.go
**/*_test.go
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*_test.go: Useenvtestfor testing Kubernetes controllers instead of fake clients
Usetestify/assertandtestify/requirefor assertions in Go tests
Write table-driven tests when testing multiple scenarios in Go
Name Go tests descriptively using format:TestFunctionName_Scenario_ExpectedBehavior
Files:
code-generator/cmd/client-gen/types/helpers_test.gocode-generator/cmd/client-gen/args/gvpackages_test.goclient-go/tests/integration/device/v1alpha1/clientset_test.gocode-generator/cmd/client-gen/generators/util/tags_test.go
**/go.mod
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use
go.modfor each service as a separate Go module with semantic import versioning
Files:
code-generator/go.mod
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
📚 Learning: 2025-12-22T16:48:13.460Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/hack/overlays/client/versioned/typed/device/v1alpha1/gpu.go:15-27
Timestamp: 2025-12-22T16:48:13.460Z
Learning: In the client-go module, files under `hack/overlays/` use the overlay pattern: they are copied into generated code directories and are not compiled standalone. These overlay files may reference types (e.g., `GPUExpansion`) that are generated by Kubernetes code-gen tools and only exist in the final destination. The build excludes overlays via grep patterns like `grep -vE '/hack/overlays/|/examples/'`. Do not flag missing type references in overlay files as compilation errors.
Applied to files:
api/hack/update-codegen.shapi/Makefilecode-generator/cmd/client-gen/args/args.gocode-generator/kube_codegen.shcode-generator/cmd/client-gen/args/gvpackages_test.gocode-generator/cmd/client-gen/generators/generator_for_group.gocode-generator/cmd/client-gen/types/helpers.gocode-generator/cmd/client-gen/types/types.gocode-generator/cmd/client-gen/generators/client_generator.gocode-generator/cmd/client-gen/generators/scheme/generator_for_scheme.gocode-generator/go.modcode-generator/cmd/client-gen/generators/generator_for_type.goclient-go/hack/update-codegen.shcode-generator/cmd/client-gen/args/gvpackages.gocode-generator/cmd/client-gen/generators/generator_for_clientset.gocode-generator/cmd/client-gen/generators/generator_for_expansion.gocode-generator/cmd/client-gen/main.goclient-go/DEVELOPMENT.mdclient-go/examples/README.mdcode-generator/cmd/client-gen/README.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use `client-go` for Kubernetes API interactions in Go code
Applied to files:
api/hack/update-codegen.shcode-generator/cmd/client-gen/args/args.go.versions.yamlcode-generator/kube_codegen.shcode-generator/cmd/client-gen/generators/generator_for_group.gocode-generator/cmd/client-gen/types/helpers.gocode-generator/cmd/client-gen/types/types.gocode-generator/cmd/client-gen/generators/client_generator.goclient-go/examples/basic-client/README.mdcode-generator/go.modcode-generator/cmd/client-gen/generators/util/tags.gocode-generator/cmd/client-gen/generators/generator_for_type.goclient-go/hack/update-codegen.shcode-generator/cmd/client-gen/generators/generator_for_clientset.gocode-generator/cmd/client-gen/generators/util/tags_test.gocode-generator/cmd/client-gen/generators/generator_for_expansion.gocode-generator/cmd/client-gen/main.goapi/DEVELOPMENT.mdapi/README.mdclient-go/DEVELOPMENT.mdclient-go/examples/README.mdcode-generator/cmd/client-gen/README.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Use `envtest` for testing Kubernetes controllers instead of fake clients
Applied to files:
code-generator/cmd/client-gen/types/helpers_test.go.versions.yamlcode-generator/cmd/client-gen/args/gvpackages_test.goclient-go/tests/integration/device/v1alpha1/clientset_test.gocode-generator/cmd/client-gen/generators/util/tags_test.goclient-go/examples/README.md
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Write table-driven tests when testing multiple scenarios in Go
Applied to files:
code-generator/cmd/client-gen/types/helpers_test.gocode-generator/cmd/client-gen/args/gvpackages_test.gocode-generator/cmd/client-gen/generators/util/tags_test.go
📚 Learning: 2025-12-22T16:16:24.320Z
Learnt from: pteranodan
Repo: NVIDIA/NVSentinel PR: 607
File: client-go/nvgrpc/config_test.go:61-80
Timestamp: 2025-12-22T16:16:24.320Z
Learning: In Go tests across the repository, avoid introducing the testify dependency for simple equality/inequality checks. Use the standard testing package assertions (t.Error, t.Errorf, t.Fatal, etc.) for straightforward checks. Reserve third-party assertion libraries for complex scenarios that require richer diagnostics or expressive matchers.
Applied to files:
code-generator/cmd/client-gen/types/helpers_test.gocode-generator/cmd/client-gen/args/gvpackages_test.goclient-go/tests/integration/device/v1alpha1/clientset_test.gocode-generator/cmd/client-gen/generators/util/tags_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to data-models/protobufs/**/*.proto : Define Protocol Buffer messages in `data-models/protobufs/` directory
Applied to files:
api/Makefile
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
Applied to files:
.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Follow standard Go conventions with gofmt and golint
Applied to files:
.versions.yaml
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*_test.go : Name Go tests descriptively using format: `TestFunctionName_Scenario_ExpectedBehavior`
Applied to files:
code-generator/cmd/client-gen/args/gvpackages_test.gocode-generator/cmd/client-gen/generators/util/tags_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: All files must include Apache 2.0 license header
Applied to files:
code-generator/LICENSE
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use meaningful variable names such as `synced` over `ok` for cache sync checks
Applied to files:
client-go/tests/integration/device/v1alpha1/clientset_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Implement proper shutdown handling with context cancellation in Go code
Applied to files:
client-go/tests/integration/device/v1alpha1/clientset_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Use separate informers for different Kubernetes resource types
Applied to files:
client-go/tests/integration/device/v1alpha1/clientset_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Prefer informers over direct API calls for watching Kubernetes resources
Applied to files:
client-go/tests/integration/device/v1alpha1/clientset_test.go
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/go.mod : Use `go.mod` for each service as a separate Go module with semantic import versioning
Applied to files:
code-generator/go.mod
📚 Learning: 2026-01-06T21:31:36.113Z
Learnt from: jtschelling
Repo: NVIDIA/NVSentinel PR: 490
File: janitor-provider/go.mod:70-70
Timestamp: 2026-01-06T21:31:36.113Z
Learning: In janitor-provider/go.mod, the dependency github.com/golang-jwt/jwt/v4 v4.5.1 is a transitive dependency from github.com/nebius/gosdk and cannot be directly upgraded without a replace directive or upstream fix in nebius/gosdk.
Applied to files:
code-generator/go.mod
📚 Learning: 2025-11-24T22:20:48.152Z
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Applies to **/*.go : Extract informer event handler setup into helper methods
Applied to files:
code-generator/go.mod
🧬 Code graph analysis (13)
api/hack/update-codegen.sh (1)
code-generator/kube_codegen.sh (2)
kube::codegen::gen_proto_bindings(125-223)kube::codegen::gen_helpers(244-474)
code-generator/cmd/client-gen/args/args.go (3)
code-generator/cmd/client-gen/types/types.go (4)
GroupVersions(101-106)GroupVersion(78-81)Group(49-49)Version(32-32)code-generator/cmd/client-gen/args/gvpackages.go (3)
NewGroupVersionsBuilder(122-126)NewGVPackagesValue(71-80)NewInputBasePathValue(44-50)code-generator/cmd/client-gen/args/gvtype.go (1)
NewGVTypesValue(39-48)
code-generator/cmd/client-gen/args/gvpackages_test.go (2)
code-generator/cmd/client-gen/types/types.go (5)
GroupVersion(78-81)GroupVersions(101-106)Group(49-49)PackageVersion(72-76)Version(32-32)code-generator/cmd/client-gen/args/gvpackages.go (3)
NewGroupVersionsBuilder(122-126)NewGVPackagesValue(71-80)NewInputBasePathValue(44-50)
code-generator/cmd/client-gen/types/helpers.go (1)
code-generator/cmd/client-gen/types/types.go (7)
GroupVersion(78-81)Group(49-49)Version(32-32)PackageVersion(72-76)GroupVersions(101-106)GroupVersionInfo(109-115)GroupInstallPackage(117-120)
code-generator/cmd/client-gen/generators/client_generator.go (4)
code-generator/cmd/client-gen/types/types.go (6)
GroupVersion(78-81)ProtobufPackage(123-126)Version(32-32)Group(49-49)GroupVersions(101-106)NewProtobufPackage(128-133)code-generator/cmd/client-gen/generators/util/tags.go (1)
MustParseClientGenTags(189-195)code-generator/cmd/client-gen/args/args.go (1)
Args(34-72)code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go (1)
GenScheme(42-53)
code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go (2)
code-generator/cmd/client-gen/types/types.go (4)
GroupVersions(101-106)GroupVersion(78-81)Group(49-49)Version(32-32)code-generator/cmd/client-gen/types/helpers.go (2)
ToGroupVersionInfo(94-109)ToGroupInstallPackages(111-122)
client-go/tests/integration/device/v1alpha1/clientset_test.go (1)
api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
api/device/v1alpha1/converter.go (2)
api/device/v1alpha1/gpu_types.go (4)
GPU(55-61)GPUList(67-71)GPUSpec(24-30)GPUStatus(35-45)api/device/v1alpha1/register.go (1)
SchemeGroupVersion(23-23)
code-generator/cmd/client-gen/generators/generator_for_type.go (4)
code-generator/cmd/client-gen/types/types.go (1)
ProtobufPackage(123-126)code-generator/cmd/client-gen/generators/client_generator.go (1)
NameSystems(49-113)code-generator/cmd/client-gen/generators/util/tags.go (3)
MustParseClientGenTags(189-195)ParseClientGenTags(199-256)Tags(158-172)metadata-collector/pkg/writer/writer.go (1)
Writer(26-28)
client-go/hack/update-codegen.sh (1)
code-generator/kube_codegen.sh (1)
kube::codegen::gen_client(523-730)
code-generator/cmd/client-gen/generators/generator_for_clientset.go (2)
code-generator/cmd/client-gen/types/types.go (4)
GroupVersions(101-106)GroupVersion(78-81)Group(49-49)Version(32-32)code-generator/cmd/client-gen/types/helpers.go (1)
ToGroupVersionInfo(94-109)
code-generator/cmd/client-gen/generators/util/tags_test.go (1)
code-generator/cmd/client-gen/generators/util/tags.go (2)
Tags(158-172)ParseClientGenTags(199-256)
code-generator/cmd/client-gen/generators/generator_for_expansion.go (1)
metadata-collector/pkg/writer/writer.go (1)
Writer(26-28)
🪛 GitHub Actions: Lint and Test
client-go/tests/integration/device/v1alpha1/clientset_test.go
[error] 1-1: license-headers-lint failed. addlicense check reported issues in the file. Run 'make license-headers-lint' to fix license headers.
🪛 LanguageTool
client-go/examples/basic-client/README.md
[style] ~16-~16: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...API_TARGET` environment variable to the exact same URI here. ## Expected Output ```text "...
(EN_WORDINESS_PREMIUM_EXACT_SAME)
client-go/examples/streaming-daemon/README.md
[style] ~19-~19: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...API_TARGET` environment variable to the exact same URI here. To stop the application, pre...
(EN_WORDINESS_PREMIUM_EXACT_SAME)
client-go/DEVELOPMENT.md
[grammar] ~13-~13: Ensure spelling is correct
Context: ... version/: [Manual] Version injection fFunctionality via ldflags. ## Workflow ### 1. Cod...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
client-go/examples/README.md
[style] ~31-~31: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...API_TARGET` environment variable to the exact same URI here.
(EN_WORDINESS_PREMIUM_EXACT_SAME)
client-go/examples/controller-shim/README.md
[style] ~18-~18: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...API_TARGET` environment variable to the exact same URI here. To stop the controller, pres...
(EN_WORDINESS_PREMIUM_EXACT_SAME)
🪛 markdownlint-cli2 (0.18.1)
api/DEVELOPMENT.md
7-7: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
api/README.md
7-7: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
client-go/examples/controller-shim/README.md
9-9: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
code-generator/cmd/client-gen/README.md
48-48: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🔇 Additional comments (34)
code-generator/LICENSE (1)
1-203: Verify license file placement and copyright holder information.The Apache License 2.0 text is correct and complete. However, ensure that:
- License placement: Verify whether
code-generator/LICENSEis the intended location, or if NVIDIA prefers a single LICENSE file at the repository root.- Copyright holder: The placeholder
Copyright [yyyy] [name of copyright owner](line 190) should be filled with NVIDIA's actual copyright notice. Confirm this is the correct format and ownership.code-generator/cmd/client-gen/generators/util/tags_test.go (2)
30-90: LGTM!The test function follows coding guidelines with a table-driven approach and uses standard testing package assertions. Coverage includes both valid tag parsing scenarios and error cases (invalid formats, conflicts).
92-154: LGTM!The test function thoroughly covers extension tag parsing with multiple scenarios including valid configurations and comprehensive error handling paths. Follows coding guidelines with table-driven tests and standard testing package assertions.
code-generator/cmd/client-gen/generators/generator_for_expansion.go (3)
35-41: LGTM!The generator struct follows the standard gengo pattern with appropriate fields for group-level generation.
43-46: LGTM!The Filter implementation correctly ensures GenerateType is invoked once per group by checking against the first type in the collection.
48-60: LGTM!The GenerateType method correctly implements idempotent generation—it checks for existing expansion files and only creates stubs when they're missing, preserving user customizations. The template generates the appropriate expansion interface stub.
code-generator/cmd/client-gen/generators/client_generator.go (1)
432-445: Verify internal-version behavior for protobuf import pathsTyped client output directories use
gv.Version.NonEmpty()(so internal becomesinternalVersion), but protobuf imports are built fromversion.Version.String()(so internal becomes""). If you ever generate typed clients for an internal version, this looks like it will importpbfrompath.Join(protoBase, groupPkgName, "")while writing clients into.../internalversion/.Please confirm one of:
- internal versions never generate typed gRPC clients, or
- protobuf stubs exist at the computed import path for internal versions, or
- you want internal protobuf packages to use
NonEmpty()as well.code-generator/cmd/client-gen/types/types.go (1)
32-141: LGTM (clean, focused helper types for codegen)Naming helpers (
NonEmpty(),PackageName()) and protobuf import helpers look consistent with their intended use in generators.code-generator/cmd/client-gen/generators/generator_for_type.go (1)
94-133: Thecontextpackage import will be present in the generated code and will not be missing.When the template expands
$.context|raw$on the function signature (line 44 of the watch template), the RawNamer—which is initialized with the ImportTracker—automatically registers the context package import. Therefore, the raw literalcontext.WithCancel(ctx)on line 50 will compile successfully.While routing
WithCancelthroughc.Universe.Function()is a valid best-practice for consistency with how other functions likefmtErrorfare handled, it is not required to fix a missing import issue.Likely an incorrect or invalid review comment.
api/hack/update-codegen.sh (1)
17-35: LGTM! Well-structured code generation script.The script follows bash best practices with strict error handling (
errexit,nounset,pipefail), correctly computes repository paths, and properly invokes the code generation functions from thekube_codegen.shlibrary. The function calls match the expected signatures forgen_proto_bindingsandgen_helpers.code-generator/cmd/client-gen/generators/util/gvpackages.go (1)
27-36: LGTM! Clean path parsing utility.The
ParsePathGroupVersionfunction correctly handles path parsing with appropriate edge case handling for paths with 0-2 segments. The logic properly splits group/version paths into their constituent parts using standard library functions.client-go/DEVELOPMENT.md (1)
1-85: Excellent development documentation.This guide provides comprehensive coverage of the development workflow, clearly explains the code generation pipeline with a helpful Mermaid diagram, and includes appropriate warnings about not editing generated files. The structure is logical and the examples are practical.
code-generator/cmd/client-gen/main.go (1)
42-78: LGTM! Well-structured code generation entry point.The main function follows good practices:
- Proper initialization of logging and argument parsing
- Deterministic output via sorted input packages (line 59)
- Argument validation before execution (lines 61-63)
- Clear error handling with descriptive messages
The TODO comment at line 46 appropriately marks future work without blocking current functionality.
code-generator/cmd/client-gen/args/gvtype.go (1)
39-48: LGTM!Constructor follows the established Kubernetes code-generator pattern for flag values with panic on invalid defaults, which is appropriate since defaults are compile-time constants.
code-generator/go.mod (1)
5-11: LGTM!Dependencies are appropriate for a Kubernetes-style code generator. The module follows the coding guideline of using
go.modfor each service as a separate Go module.api/Makefile (1)
55-59: LGTM!The
cleantarget properly removes both the generated protobuf directory and thezz_generated.*.gofiles. Usingfindwith-deleteis efficient.code-generator/cmd/client-gen/args/gvpackages.go (1)
128-162: LGTM!The
update()method correctly aggregates versions per group, sorts group names for deterministic output, and properly resets the target slice before building. This ensures consistent code generation across runs.code-generator/cmd/client-gen/args/args.go (2)
114-132: LGTM!The
Validate()method properly checks all required fields and returns descriptive error messages. Error wrapping follows the coding guideline pattern withfmt.Errorf.
145-152: LGTM!The
mapFlagNamehelper cleanly provides backward compatibility for the legacy--clientset-pathflag by remapping it to--output-pkg. Good use of closure composition.code-generator/cmd/client-gen/generators/generator_for_clientset.go (3)
76-101: LGTM!The
GenerateTypemethod correctly builds the template context with all required types and functions from the nvgrpc package. The template rendering follows the established Kubernetes code-generator patterns while adapting for gRPC transport. This aligns with the coding guideline to useclient-gopatterns for Kubernetes API interactions.
124-144: LGTM!The
NewForConfigtemplate correctly implements defensive patterns: nil config check, shallow copy to prevent mutation, and proper error propagation from connection setup.
182-189: LGTM!The
Newconstructor provides a simple path for users who already have a gRPC connection, which is useful for testing with mock connections or shared connection pools.code-generator/cmd/client-gen/generators/generator_for_group.go (5)
1-35: License headers and imports look correct.The file properly attributes the original Kubernetes source and NVIDIA modifications. Imports are appropriate for the code generation task.
37-54: Struct design follows upstream patterns correctly.The
genGroupstruct appropriately encapsulates generation state including the single-invocation guard (called) for ensuringGenerateTyperuns once per group.
56-74: Generator interface methods implemented correctly.The
Filter,Namers, andImportsmethods follow the expectedgenerator.Generatorinterface pattern from gengo.
76-128: GenerateType implementation is sound.The method correctly:
- Extracts optional
+groupNametag overrides from package comments- Handles errors from tag parsing appropriately
- Iterates over types to generate namespaced vs non-namespaced getters based on client-gen tags
- Propagates template errors via
sw.Error()Note: The generated code uses
logr.Logger(lines 99-100) rather thanlog/slog. This aligns with Kubernetes client-go conventions wherelogris the standard logging facade, so this is appropriate for this context.
130-156: Templates are well-structured and follow Kubernetes patterns.The interface and client struct templates correctly define the gRPC client surface with
ClientConn()accessor and type-specific getters. The namespaced vs non-namespaced getter implementations properly delegate to constructor functions.code-generator/kube_codegen.sh (7)
22-26: Shell options and script root setup are correct.The script uses
set -o errexit,set -o nounset, andset -o pipefailwhich are best practices for robust Bash scripts. TheKUBE_CODEGEN_ROOTis correctly resolved using portable path handling.
28-34: Version retrieval function works but is fragile with complex YAML.The
get_versionfunction uses simple grep/sed to parse YAML. This works for flat key-value pairs but may fail on nested structures or multi-line values.Given that
.versions.yamlappears to use simple flat structure based on the AI summary (showing entries likegoverter: v1.9.3), this is acceptable for the current use case.
94-108: Internal helper functions are well-designed.The
findzandgrepwrappers correctly handle cross-repo usage and exclude common non-source directories (.git,_output,vendor). Using null-delimited output (-print0) is the correct approach for safely handling filenames with special characters.
125-223: Proto generation function is well-structured.The function correctly:
- Validates input arguments and handles unknown flags
- Installs required protoc plugins
- Discovers proto files and cleans existing generated files before regeneration
- Uses null-delimited processing throughout for safety
668-729: Client generation logic is correctly implemented.The function properly:
- Cleans existing generated code before regeneration
- Builds input arguments array correctly
- Passes all required flags to
client-gen,lister-gen, andinformer-gen- Conditionally generates watch-related code (listers/informers) only when
--with-watchis specified
244-295: Helper generator installation and execution is robust.The function correctly installs upstream Kubernetes code-gen tools and handles the goverter installation via a temporary module. The trap for cleanup (line 301) ensures the temp directory is removed even on error.
303-310: No action required. Go 1.25 is a valid and current stable version as of January 2026, making the specification in line 305 correct.
| goverter: 'v1.9.3' | ||
| kubernetes_code_gen: 'v0.34.1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
goverter v1.9.3 release github jmattheis
💡 Result:
I couldn't find a v1.9.3 release. The project repo is at github.com/jmattheis/goverter [1], and the official install docs list the latest release as v1.9.2. [2]
Sources:
- GitHub repository: github.com/jmattheis/goverter. [1]
- Goverter install page (shows "Latest version: v1.9.2"). [2]
🌐 Web query:
kubernetes code-generator v0.34.1 release
💡 Result:
Yes — the k8s module version k8s.io/code-generator v0.34.1 is published and in use (appears in dependency lists and Go modules). Sources showing v0.34.1 include a project go.mod listing and dependency docs. [1][2][3]
Sources:
- Kubernetes code-generator repository (project page). [1]
- Example go.mod showing k8s.io/code-generator => v0.34.1 (Volcano mirror). [2]
- Elastic Cloud on Kubernetes third-party dependencies listing k8s.io/code-generator v0.34.1. [3]
References:
[1] https://github.com/kubernetes/code-generator
[2] https://gitee.com/mirrors/Volcano/blob/master/go.mod
[3] https://www.elastic.co/docs/reference/cloud-on-k8s/third-party-dependencies/3_2_0
🌐 Web query:
goverter security vulnerabilities advisories
💡 Result:
I couldn’t find any published security advisories or CVEs for "goverter" (jmattheis/goverter). Sources checked: the project repository and docs, pkg.go.dev entry, and the GitHub Advisory Database (no matching advisories). [1][2][3]
If you want, I can (a) search additional vulnerability databases (NVD, GitLab, OSV, vendor lists), (b) scan a specific repo version for known-vuln dependencies, or (c) run a quick static/security check on the code—which would you prefer?
Sources:
- jmattheis/goverter (GitHub). [1]
- goverter package page (pkg.go.dev). [2]
- GitHub Advisory Database / browsing advisories (no goverter matches). [3]
🌐 Web query:
kubernetes code-generator security vulnerabilities advisories
💡 Result:
Short answer: I could not find any published security advisories or CVEs that specifically name k8s.io/code-generator (the Kubernetes code-generator tooling) as the vulnerable component. Kubernetes project advisories and CVEs do exist for related components (e.g., kubelet/gitRepo, Image Builder, various k8s modules) — so dependents that vendor or consume code-generator outputs can be affected — but there’s no dedicated code-generator advisory in the official CVE feed or NVD results I found. [1][2][3]
Pointers for ongoing tracking:
- Kubernetes official CVE feed (watch for new entries). [1]
- Kubernetes Discuss / Security announcements for advisories such as CVE-2024-10220 (gitRepo/kubelet) and other k8s component advisories. [2][3]
- GitHub security advisories for the k8s repositories (kubernetes, k8s.io/code-generator, k8s.io/gengo) and the NVD for vendor-assigned CVEs.
- If you use generated clients/controllers, scan your generated code and upstream k8s module versions and update when k8s modules are bumped (many projects list code-generator in dependency updates). [4][5]
Sources:
- Kubernetes official CVE feed / security listing. [k8s.io official CVE feed]. [1]
- Kubernetes security announcement / Discuss thread for CVE-2024-10220 (gitRepo kubelet). [2]
- External vulnerability writeup summarizing CVE-2024-10220. [3]
- Discussion about code-generator/gengo tooling changes and deprecation (impacts to generate-groups). [4]
- Package/change logs showing k8s.io/code-generator version bumps in projects (indicative of dependency tracking). [5]
Would you like me to:
- monitor the official Kubernetes CVE feed and send alerts for any future advisories that mention code-generator, or
- run a focused search for advisories affecting a specific version you’re using?
Update goverter version to v1.9.2; kubernetes-code-generator v0.34.1 is valid.
The specified goverter version v1.9.3 does not exist. The latest release is v1.9.2. The kubernetes-code-generator v0.34.1 is valid and published. No known security advisories were found for either tool.
🤖 Prompt for AI Agents
In @.versions.yaml around lines 49 - 50, The .versions.yaml entry for goverter
is incorrect—update the goverter key value from 'v1.9.3' to the existing release
'v1.9.2' while leaving kubernetes_code_gen at 'v0.34.1' unchanged; locate the
goverter entry in the file and replace its version string so the key "goverter"
reads 'v1.9.2'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v1.9.3 was released on 1/6/26, https://github.com/jmattheis/goverter/releases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
goverter v1.9.3 release january 2026
💡 Result:
I searched but couldn't find any public release notes, download, or repository for "goverter v1.9.3" (January 2026). Do you mean a different name/spelling or can you share a link or more context (project homepage, GitHub/GitLab repo)?
🌐 Web query:
github jmattheis goverter releases latest version
💡 Result:
The latest released version is v1.9.2. [1][2]
Sources:
- repository README/releases information. [1]
- official install docs showing go install [email protected]. [2]
@pteranodan, thank you for the clarification!
I've searched multiple times but my results consistently show v1.9.2 as the latest goverter release. However, it's entirely possible that a release from January 6th (just 3 days ago) hasn't been fully indexed by search engines yet.
Could you confirm that you've directly checked the releases page and can see v1.9.3 listed there? If so, then the version specified in .versions.yaml is correct, and the original review comment flagging it as invalid should be disregarded.
For kubernetes_code_gen: 'v0.34.1', that version is confirmed to be valid and published.
🧠 Learnings used
Learnt from: CR
Repo: NVIDIA/NVSentinel PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T22:20:48.152Z
Learning: Keep Go dependencies minimal and up-to-date
| - `listers/`: [Generated] Type-safe listers. **Do not edit manually.** | ||
| - `informers/`: [Generated] Shared Index Informers. **Do not edit manually.** | ||
| - `nvgrpc/`: [Manual] The gRPC transport layer, interceptors, and connection management logic. | ||
| - `version/`: [Manual] Version injection fFunctionality via `ldflags`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in version description.
There's a typographical error: "fFunctionality" should be "Functionality".
📝 Proposed fix
-- `version/`: [Manual] Version injection fFunctionality via `ldflags`.
+- `version/`: [Manual] Version injection functionality via `ldflags`.📝 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.
| - `version/`: [Manual] Version injection fFunctionality via `ldflags`. | |
| - `version/`: [Manual] Version injection functionality via `ldflags`. |
🧰 Tools
🪛 LanguageTool
[grammar] ~13-~13: Ensure spelling is correct
Context: ... version/: [Manual] Version injection fFunctionality via ldflags. ## Workflow ### 1. Cod...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🤖 Prompt for AI Agents
In @client-go/DEVELOPMENT.md at line 13, Fix the typo in DEVELOPMENT.md by
updating the description for the `version/` entry: replace "fFunctionality" with
"Functionality" so the line reads "`version/`: [Manual] Version injection
Functionality via `ldflags`."
| **Note:** `sudo` is required because the default socket path is in `/var/run/`. If you started the server with a non-default target, override the socket path with the `NVIDIA_DEVICE_API_TARGET` environment variable to the exact same URI here. | ||
|
|
||
| To stop the application, press `Ctrl+C` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tighten wording (“exact same”)
Minor readability nit: “the exact same URI” → “the same URI”.
🧰 Tools
🪛 LanguageTool
[style] ~19-~19: ‘exact same’ might be wordy. Consider a shorter alternative.
Context: ...API_TARGET` environment variable to the exact same URI here. To stop the application, pre...
(EN_WORDINESS_PREMIUM_EXACT_SAME)
🤖 Prompt for AI Agents
In @client-go/examples/streaming-daemon/README.md around lines 19 - 21, Change
the phrasing in the README note to tighten wording: replace “the exact same URI”
with “the same URI” in the sentence that tells users to override the socket path
with the NVIDIA_DEVICE_API_TARGET environment variable so it reads “…override
the socket path with the NVIDIA_DEVICE_API_TARGET environment variable to the
same URI here.” to improve readability.
| @@ -0,0 +1,336 @@ | |||
| package v1alpha1_test | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing license header.
The pipeline failure indicates this file is missing the required Apache 2.0 license header. Run make license-headers-lint to add it.
🧰 Tools
🪛 GitHub Actions: Lint and Test
[error] 1-1: license-headers-lint failed. addlicense check reported issues in the file. Run 'make license-headers-lint' to fix license headers.
🤖 Prompt for AI Agents
In @client-go/tests/integration/device/v1alpha1/clientset_test.go at line 1,
This file is missing the required Apache 2.0 license header; add the standard
Apache 2.0 license comment block at the top of the file above the package
declaration in client-go/tests/integration/device/v1alpha1/clientset_test.go,
then run the repository's license linter (make license-headers-lint) to ensure
formatting and compliance.
| func NewInputBasePathValue(builder *groupVersionsBuilder, def string) *inputBasePathValue { | ||
| v := &inputBasePathValue{ | ||
| builder: builder, | ||
| } | ||
| v.Set(def) | ||
| return v | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ignored error from Set call in constructor.
NewInputBasePathValue calls v.Set(def) but ignores the returned error. If def is an invalid value that causes builder.update() to fail, the error is silently discarded.
Consider panicking on error for consistency with NewGVPackagesValue and NewGVTypesValue, or validate that default values cannot cause errors.
Suggested fix
func NewInputBasePathValue(builder *groupVersionsBuilder, def string) *inputBasePathValue {
v := &inputBasePathValue{
builder: builder,
}
- v.Set(def)
+ if err := v.Set(def); err != nil {
+ panic(err)
+ }
return v
}📝 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.
| func NewInputBasePathValue(builder *groupVersionsBuilder, def string) *inputBasePathValue { | |
| v := &inputBasePathValue{ | |
| builder: builder, | |
| } | |
| v.Set(def) | |
| return v | |
| } | |
| func NewInputBasePathValue(builder *groupVersionsBuilder, def string) *inputBasePathValue { | |
| v := &inputBasePathValue{ | |
| builder: builder, | |
| } | |
| if err := v.Set(def); err != nil { | |
| panic(err) | |
| } | |
| return v | |
| } |
🤖 Prompt for AI Agents
In @code-generator/cmd/client-gen/args/gvpackages.go around lines 44 - 50,
NewInputBasePathValue calls v.Set(def) and ignores its returned error which can
hide builder.update() failures; update the constructor to check the error
returned by inputBasePathValue.Set(def) and panic on non-nil error (consistent
with NewGVPackagesValue/NewGVTypesValue) so invalid default values fail
fast—locate NewInputBasePathValue and inputBasePathValue.Set (which calls
builder.update()) and change the call to capture err and panic with a
descriptive message if err != nil.
| func sanitizePackagePaths(context *generator.Context, args *args.Args) error { | ||
| for i := range args.Groups { | ||
| pkg := &args.Groups[i] | ||
| for j := range pkg.Versions { | ||
| ver := &pkg.Versions[j] | ||
| input := ver.Package | ||
| p := context.Universe[input] | ||
| if p == nil || p.Name == "" { | ||
| pkgs, err := context.FindPackages(input) | ||
| if err != nil { | ||
| return fmt.Errorf("can't find input package %q: %w", input, err) | ||
| } | ||
| p = context.Universe[pkgs[0]] | ||
| if p == nil { | ||
| return fmt.Errorf("can't find input package %q in universe", input) | ||
| } | ||
| ver.Package = p.Path | ||
| } | ||
| } | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard against empty FindPackages() results to avoid panic
sanitizePackagePaths assumes pkgs[0] exists when FindPackages(input) succeeds. If it returns an empty slice, this panics.
Proposed fix
@@
pkgs, err := context.FindPackages(input)
if err != nil {
return fmt.Errorf("can't find input package %q: %w", input, err)
}
+ if len(pkgs) == 0 {
+ return fmt.Errorf("can't find input package %q: no packages matched", input)
+ }
p = context.Universe[pkgs[0]]
if p == nil {
return fmt.Errorf("can't find input package %q in universe", input)
}📝 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.
| func sanitizePackagePaths(context *generator.Context, args *args.Args) error { | |
| for i := range args.Groups { | |
| pkg := &args.Groups[i] | |
| for j := range pkg.Versions { | |
| ver := &pkg.Versions[j] | |
| input := ver.Package | |
| p := context.Universe[input] | |
| if p == nil || p.Name == "" { | |
| pkgs, err := context.FindPackages(input) | |
| if err != nil { | |
| return fmt.Errorf("can't find input package %q: %w", input, err) | |
| } | |
| p = context.Universe[pkgs[0]] | |
| if p == nil { | |
| return fmt.Errorf("can't find input package %q in universe", input) | |
| } | |
| ver.Package = p.Path | |
| } | |
| } | |
| } | |
| return nil | |
| } | |
| func sanitizePackagePaths(context *generator.Context, args *args.Args) error { | |
| for i := range args.Groups { | |
| pkg := &args.Groups[i] | |
| for j := range pkg.Versions { | |
| ver := &pkg.Versions[j] | |
| input := ver.Package | |
| p := context.Universe[input] | |
| if p == nil || p.Name == "" { | |
| pkgs, err := context.FindPackages(input) | |
| if err != nil { | |
| return fmt.Errorf("can't find input package %q: %w", input, err) | |
| } | |
| if len(pkgs) == 0 { | |
| return fmt.Errorf("can't find input package %q: no packages matched", input) | |
| } | |
| p = context.Universe[pkgs[0]] | |
| if p == nil { | |
| return fmt.Errorf("can't find input package %q in universe", input) | |
| } | |
| ver.Package = p.Path | |
| } | |
| } | |
| } | |
| return nil | |
| } |
🤖 Prompt for AI Agents
In @code-generator/cmd/client-gen/generators/client_generator.go around lines
334 - 355, sanitizePackagePaths assumes context.FindPackages(input) returns a
non-empty slice and dereferences pkgs[0], which can panic if the slice is empty;
after calling context.FindPackages(input) in sanitizePackagePaths, check if
len(pkgs) == 0 and return a descriptive error (e.g., "no packages found for
input %q") before accessing pkgs[0], ensuring ver.Package is only set when a
package is actually available.
| // Input returns the input override package path and the type. | ||
| func (e *extension) Input() (string, string) { | ||
| parts := strings.Split(e.InputTypeOverride, ".") | ||
| return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".") | ||
| } | ||
|
|
||
| // Result returns the result override package path and the type. | ||
| func (e *extension) Result() (string, string) { | ||
| parts := strings.Split(e.ResultTypeOverride, ".") | ||
| return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extension.Input() / Result() return order doesn’t match the comment
Both functions claim to return “package path and the type” but currently return (type, package).
Proposed fix (package, type)
@@
func (e *extension) Input() (string, string) {
parts := strings.Split(e.InputTypeOverride, ".")
- return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".")
+ return strings.Join(parts[0:len(parts)-1], "."), parts[len(parts)-1]
}
@@
func (e *extension) Result() (string, string) {
parts := strings.Split(e.ResultTypeOverride, ".")
- return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".")
+ return strings.Join(parts[0:len(parts)-1], "."), parts[len(parts)-1]
}📝 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.
| // Input returns the input override package path and the type. | |
| func (e *extension) Input() (string, string) { | |
| parts := strings.Split(e.InputTypeOverride, ".") | |
| return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".") | |
| } | |
| // Result returns the result override package path and the type. | |
| func (e *extension) Result() (string, string) { | |
| parts := strings.Split(e.ResultTypeOverride, ".") | |
| return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".") | |
| } | |
| // Input returns the input override package path and the type. | |
| func (e *extension) Input() (string, string) { | |
| parts := strings.Split(e.InputTypeOverride, ".") | |
| return strings.Join(parts[0:len(parts)-1], "."), parts[len(parts)-1] | |
| } | |
| // Result returns the result override package path and the type. | |
| func (e *extension) Result() (string, string) { | |
| parts := strings.Split(e.ResultTypeOverride, ".") | |
| return strings.Join(parts[0:len(parts)-1], "."), parts[len(parts)-1] | |
| } |
🤖 Prompt for AI Agents
In @code-generator/cmd/client-gen/generators/util/tags.go around lines 145 -
155, The Input() and Result() methods currently return (type, package) but their
comments say they should return (package path, type); fix both by swapping the
return values so they return strings.Join(parts[0:len(parts)-1], ".") first (the
package path) and parts[len(parts)-1] second (the type); do this for
extension.Input() and extension.Result() while preserving the current split
logic and single-segment behavior.
| // Tags represents a genclient configuration for a single type. | ||
| type Tags struct { | ||
| // +genclient | ||
| GenerateClient bool | ||
| // +genclient:nonNamespaced | ||
| NonNamespaced bool | ||
| // +genclient:noStatus | ||
| NoStatus bool | ||
| // +genclient:noVerbs | ||
| NoVerbs bool | ||
| // +genclient:skipVerbs=get,update | ||
| // +genclient:onlyVerbs=create,delete | ||
| SkipVerbs []string | ||
| // +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale | ||
| Extensions []extension | ||
| } | ||
|
|
||
| // HasVerb returns true if we should include the given verb in final client interface and | ||
| // generate the function for it. | ||
| func (t Tags) HasVerb(verb string) bool { | ||
| if len(t.SkipVerbs) == 0 { | ||
| return true | ||
| } | ||
| for _, s := range t.SkipVerbs { | ||
| if verb == s { | ||
| return false | ||
| } | ||
| } | ||
| return true | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tags.HasVerb should honor +genclient:noVerbs
Right now NoVerbs doesn’t affect generation unless every generator special-cases it (they don’t in the provided files), so +genclient:noVerbs is effectively ignored.
Proposed fix
@@
func (t Tags) HasVerb(verb string) bool {
+ if t.NoVerbs {
+ return false
+ }
if len(t.SkipVerbs) == 0 {
return true
}📝 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.
| // Tags represents a genclient configuration for a single type. | |
| type Tags struct { | |
| // +genclient | |
| GenerateClient bool | |
| // +genclient:nonNamespaced | |
| NonNamespaced bool | |
| // +genclient:noStatus | |
| NoStatus bool | |
| // +genclient:noVerbs | |
| NoVerbs bool | |
| // +genclient:skipVerbs=get,update | |
| // +genclient:onlyVerbs=create,delete | |
| SkipVerbs []string | |
| // +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale | |
| Extensions []extension | |
| } | |
| // HasVerb returns true if we should include the given verb in final client interface and | |
| // generate the function for it. | |
| func (t Tags) HasVerb(verb string) bool { | |
| if len(t.SkipVerbs) == 0 { | |
| return true | |
| } | |
| for _, s := range t.SkipVerbs { | |
| if verb == s { | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| // Tags represents a genclient configuration for a single type. | |
| type Tags struct { | |
| // +genclient | |
| GenerateClient bool | |
| // +genclient:nonNamespaced | |
| NonNamespaced bool | |
| // +genclient:noStatus | |
| NoStatus bool | |
| // +genclient:noVerbs | |
| NoVerbs bool | |
| // +genclient:skipVerbs=get,update | |
| // +genclient:onlyVerbs=create,delete | |
| SkipVerbs []string | |
| // +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale | |
| Extensions []extension | |
| } | |
| // HasVerb returns true if we should include the given verb in final client interface and | |
| // generate the function for it. | |
| func (t Tags) HasVerb(verb string) bool { | |
| if t.NoVerbs { | |
| return false | |
| } | |
| if len(t.SkipVerbs) == 0 { | |
| return true | |
| } | |
| for _, s := range t.SkipVerbs { | |
| if verb == s { | |
| return false | |
| } | |
| } | |
| return true | |
| } |
🤖 Prompt for AI Agents
In @code-generator/cmd/client-gen/generators/util/tags.go around lines 157 -
186, The HasVerb method currently ignores the Tags.NoVerbs flag so
+genclient:noVerbs is ineffective; modify Tags.HasVerb to first check if
t.NoVerbs is true and immediately return false for any verb, otherwise preserve
the existing SkipVerbs logic (iterate t.SkipVerbs and return false if verb
matches, true otherwise). Update the Tags.HasVerb implementation to reference
the NoVerbs field before consulting SkipVerbs so generators honor
+genclient:noVerbs.
| if v, exists := values[genClientPrefix+"skipVerbs"]; exists { | ||
| ret.SkipVerbs = strings.Split(v[0], ",") | ||
| } | ||
| if v, exists := values[genClientPrefix+"onlyVerbs"]; exists || len(onlyVerbs) > 0 { | ||
| if len(v) > 0 { | ||
| onlyVerbs = append(onlyVerbs, strings.Split(v[0], ",")...) | ||
| } | ||
| skipVerbs := []string{} | ||
| for _, m := range SupportedVerbs { | ||
| skip := true | ||
| for _, o := range onlyVerbs { | ||
| if o == m { | ||
| skip = false | ||
| break | ||
| } | ||
| } | ||
| // Check for conflicts | ||
| for _, v := range skipVerbs { | ||
| if v == m { | ||
| return ret, fmt.Errorf("verb %q used both in genclient:skipVerbs and genclient:onlyVerbs", v) | ||
| } | ||
| } | ||
| if skip { | ||
| skipVerbs = append(skipVerbs, m) | ||
| } | ||
| } | ||
| ret.SkipVerbs = skipVerbs | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix skipVerbs vs onlyVerbs conflict handling (and avoid silently dropping skipVerbs)
If +genclient:skipVerbs=... is set and +genclient:onlyVerbs=... is also set (or implied via readonly), current logic overwrites ret.SkipVerbs and the “conflict” check doesn’t actually compare against the user-provided skip list.
Proposed fix (fail fast on conflicts)
@@
if v, exists := values[genClientPrefix+"skipVerbs"]; exists {
ret.SkipVerbs = strings.Split(v[0], ",")
}
if v, exists := values[genClientPrefix+"onlyVerbs"]; exists || len(onlyVerbs) > 0 {
+ if len(ret.SkipVerbs) > 0 {
+ return ret, fmt.Errorf("cannot use both genclient:skipVerbs and genclient:onlyVerbs")
+ }
if len(v) > 0 {
onlyVerbs = append(onlyVerbs, strings.Split(v[0], ",")...)
}
skipVerbs := []string{}
for _, m := range SupportedVerbs {
skip := true
for _, o := range onlyVerbs {
if o == m {
skip = false
break
}
}
- // Check for conflicts
- for _, v := range skipVerbs {
- if v == m {
- return ret, fmt.Errorf("verb %q used both in genclient:skipVerbs and genclient:onlyVerbs", v)
- }
- }
if skip {
skipVerbs = append(skipVerbs, m)
}
}
ret.SkipVerbs = skipVerbs
}🤖 Prompt for AI Agents
In @code-generator/cmd/client-gen/generators/util/tags.go around lines 223 -
250, The conflict logic currently overwrites ret.SkipVerbs when onlyVerbs is
specified and never compares the user-provided skip list, causing silent drops;
update the block handling genClientPrefix+"onlyVerbs" so it first collects
onlyVerbs (appending v[0] if present), then check for any intersection between
the existing ret.SkipVerbs (from genClientPrefix+"skipVerbs") and onlyVerbs and
return an error if any verb appears in both, and only if no conflict compute the
new skip list from SupportedVerbs (or keep the original ret.SkipVerbs when
onlyVerbs is empty); ensure you reference and preserve ret.SkipVerbs, onlyVerbs,
SupportedVerbs and the genClientPrefix+"skipVerbs"/+"onlyVerbs" values during
these checks.
| func defaultVersion(versions []PackageVersion) Version { | ||
| var versionStrings []string | ||
| for _, version := range versions { | ||
| versionStrings = append(versionStrings, version.Version.String()) | ||
| } | ||
| sort.Sort(sortableSliceOfVersions(versionStrings)) | ||
| return Version(versionStrings[len(versionStrings)-1]) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential panic if versions is empty.
defaultVersion accesses versionStrings[len(versionStrings)-1] without checking if the slice is empty. If called with an empty versions slice, this will panic with an index out of range error.
Since this is copied from upstream for compatibility, consider adding a defensive check or documenting the precondition that versions must be non-empty.
🤖 Prompt for AI Agents
In @code-generator/cmd/client-gen/types/helpers.go around lines 84 - 91,
defaultVersion can panic when called with an empty versions slice because it
indexes versionStrings[len(versionStrings)-1]; add a defensive check in
defaultVersion to return a sensible zero value or an error when len(versions)==0
(for example return Version("") or a defined default) and document the
precondition; ensure you still build the sorted slice using
sortableSliceOfVersions(versionStrings) and reference the
PackageVersion.Version.String() mapping unchanged, and update any callers or add
tests to assert behavior when versions is empty so callers handle the empty-case
consistently.
Summary
This PR introduces a generated
client-goSDK for the NVIDIA Device API, enabling Kubernetes-native patterns (Informers, Listers,controller-runtime) over a node-local gRPC connection.It also slightly refactors the internal protobuf representations in the
apimodule to ensure seamless compatibility with the Kubernetes ecosystem without changing the core of the API.Key Changes
1. API Module Refactor (
api/)Refactored the API layer to support stricter interface compliance and standard client machinery:
ObjectMetaandListMetamessage types to satisfymetav1interface requirements without needing custom conversions.resource_versionfields to enable the optimistic concurrency and Watch semantics required by K8s caching layers.deepcopymethods) handled by a centralized code-generator library viamake code-gen.2. Go Client SDK (
client-go/)Adds a generated client that provides the standard
client-goexperience over a node-local gRPC connection via Unix domain sockets (UDS).Clientset,Listers, andInformers.3. Code Generation (
code-generator)Introduces a dedicated directory for managing all code generation:
kube_codegen.sh, a reusable library for orchestrating generation of Go bindings, gRPC interfaces, helpers, and clients.client-genwhich handles gRPC service mapping to the standard K8s client interfaces.3. Documentation & Examples
basic-client(foundational),streaming-daemon(Watch/Interceptors), andcontroller-shim(Informer Injection).fake-serverto mock the Device API for local development/verification.README.md's,DEVELOPMENT.md's, andCONFIGURATION.md's for each component.Future Extensibility
Update,Patch) to existing resources only requires updating the// +genclienttags in the API module, implementing the corresponding service methods on the server.client-genmachinery.apimodule with standard markers will automatically generate the full stack: DeepCopy methods, Proto-to-Go conversions, Typed Clients, Informers, and Listers.Type of Change
Component(s) Affected
Testing
make test)fake-server.Checklist
Review Guidance
This PR includes a significant amount of generated code which is collapsed by default in the diff (via
.gitattributes).Files to Skip:
api/**/zz_generated.*.go(DeepCopy, Conversions, etc.)*.pb.go(Protobuf bindings)client-go/{client,informers,listers}/**(Standard K8s client machinery)Focus Areas:
api/(Go types),client-go/nvgrpc/(Connection logic), andcode-generator/client-go/examples/Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.