NO-ISSUE: Add Lease type to the private API - #379
Conversation
Add a `Lease` resource type to the private API, inspired by the Kubernetes Lease concept. This is a coordination primitive that will be used to implement leader election for the controller, allowing multiple instances to run while only one actively reconciles. The `Lease` message has a `LeaseSpec` with fields for holder identity, lease duration, acquire and renew timestamps, and a transition counter. The `Leases` gRPC service provides standard CRUD plus Signal operations. This commit includes: - Proto definitions for `lease_type.proto` and `leases_service.proto`. - Generated Go code from `buf generate`. - Addition of `Lease` to the `Event` oneof payload. - Database migration creating the `leases` table. - `PrivateLeasesServer` implementation delegating to `GenericServer`. - Registration in the gRPC server command. - `Lease` case in `GenericServer.setPayload` for event notifications. - Support for `google.protobuf.Duration` in the custom JSON encoder. - Unit tests for the lease server. Signed-off-by: Juan Hernandez <juan.hernandez@redhat.com>
|
@jhernand: This pull request explicitly references no jira issue. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jhernand The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
WalkthroughThis PR introduces a new private gRPC leases service for distributed coordination. It includes new protobuf definitions for Lease type and LeasesService with CRUD operations, a PostgreSQL migration creating the leases table, a PrivateLeasesServer implementation with builder pattern, integration into the gRPC server startup, JSON encoding support for Duration types, and comprehensive tests validating core functionality. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
internal/servers/private_leases_server_test.go (1)
113-288: Good test coverage, but consider adding Signal RPC test.The behavior tests comprehensively cover Create, List (with variations), Get, Update, and Delete operations. However, there's no test for the
SignalRPC.Consider adding a test case:
It("Signals a lease", func() { createResponse, err := leasesServer.Create(ctx, ...) Expect(err).ToNot(HaveOccurred()) _, err = leasesServer.Signal(ctx, privatev1.LeasesSignalRequest_builder{ Id: createResponse.GetObject().GetId(), }.Build()) Expect(err).ToNot(HaveOccurred()) })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/servers/private_leases_server_test.go` around lines 113 - 288, Add a new test It("Signals a lease", ...) inside the existing Describe("Behaviour") block that creates a lease using leasesServer.Create (as in other tests), then calls leasesServer.Signal with a privatev1.LeasesSignalRequest_builder containing the created object's Id, and asserts no error is returned; reference the leasesServer.Signal method and privatev1.LeasesSignalRequest_builder to locate where to add the call and assertions consistent with other tests.internal/servers/private_leases_server.go (2)
70-74: Documentation inconsistency:SetTenancyLogicshould note that it's mandatory.
SetLogger(line 52) documents that it's mandatory, andBuild()validates bothloggerandtenancyLogic. Consider updating the doc comment for consistency.📝 Suggested doc update
-// SetTenancyLogic sets the tenancy logic that will be used to determine the tenants for objects. +// SetTenancyLogic sets the tenancy logic that will be used to determine the tenants for objects. +// This is mandatory. func (b *PrivateLeasesServerBuilder) SetTenancyLogic(value auth.TenancyLogic) *PrivateLeasesServerBuilder {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/servers/private_leases_server.go` around lines 70 - 74, The doc comment for SetTenancyLogic is inconsistent with SetLogger: update the comment for the SetTenancyLogic method to state that providing a tenancyLogic is mandatory (since Build() validates both logger and tenancyLogic), mirroring the wording/style used in SetLogger so callers know SetTenancyLogic must be set before Build is called; reference the SetTenancyLogic method and the Build validation that checks tenancyLogic to align documentation with behavior.
43-44: Consider removing unusedloggerfield.The
loggerfield is assigned duringBuild()but is never read in any of thePrivateLeasesServermethods. All logging is handled by the embeddedgenericserver. If this field is reserved for future use, consider adding a comment; otherwise, removing it would reduce confusion.♻️ Suggested cleanup
type PrivateLeasesServer struct { privatev1.UnimplementedLeasesServer - logger *slog.Logger generic *GenericServer[*privatev1.Lease] }And in
Build():result = &PrivateLeasesServer{ - logger: b.logger, generic: generic, }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/servers/private_leases_server.go` around lines 43 - 44, The struct field logger on PrivateLeasesServer is never read—remove the unused logger field declaration and its assignment in Build() (or, if you intend to keep it for future use, add a clear comment above the field explaining why it’s reserved), and update any imports/usages (e.g., references in Build() that set logger) accordingly; keep the embedded generic *GenericServer[*privatev1.Lease] as the authoritative logger source (PrivateLeasesServer, Build(), logger).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@internal/servers/private_leases_server_test.go`:
- Around line 113-288: Add a new test It("Signals a lease", ...) inside the
existing Describe("Behaviour") block that creates a lease using
leasesServer.Create (as in other tests), then calls leasesServer.Signal with a
privatev1.LeasesSignalRequest_builder containing the created object's Id, and
asserts no error is returned; reference the leasesServer.Signal method and
privatev1.LeasesSignalRequest_builder to locate where to add the call and
assertions consistent with other tests.
In `@internal/servers/private_leases_server.go`:
- Around line 70-74: The doc comment for SetTenancyLogic is inconsistent with
SetLogger: update the comment for the SetTenancyLogic method to state that
providing a tenancyLogic is mandatory (since Build() validates both logger and
tenancyLogic), mirroring the wording/style used in SetLogger so callers know
SetTenancyLogic must be set before Build is called; reference the
SetTenancyLogic method and the Build validation that checks tenancyLogic to
align documentation with behavior.
- Around line 43-44: The struct field logger on PrivateLeasesServer is never
read—remove the unused logger field declaration and its assignment in Build()
(or, if you intend to keep it for future use, add a clear comment above the
field explaining why it’s reserved), and update any imports/usages (e.g.,
references in Build() that set logger) accordingly; keep the embedded generic
*GenericServer[*privatev1.Lease] as the authoritative logger source
(PrivateLeasesServer, Build(), logger).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 82a0895f-4133-4db9-a750-f92fc1ce1099
⛔ Files ignored due to path filters (8)
internal/api/osac/private/v1/event_type.pb.gois excluded by!**/*.pb.gointernal/api/osac/private/v1/event_type_protoopaque.pb.gois excluded by!**/*.pb.gointernal/api/osac/private/v1/lease_type.pb.gois excluded by!**/*.pb.gointernal/api/osac/private/v1/lease_type_protoopaque.pb.gois excluded by!**/*.pb.gointernal/api/osac/private/v1/leases_service.pb.gois excluded by!**/*.pb.gointernal/api/osac/private/v1/leases_service.pb.gw.gois excluded by!**/*.pb.gw.gointernal/api/osac/private/v1/leases_service_grpc.pb.gois excluded by!**/*.pb.gointernal/api/osac/private/v1/leases_service_protoopaque.pb.gois excluded by!**/*.pb.go
📒 Files selected for processing (9)
internal/cmd/service/start/grpcserver/start_grpc_server_cmd.gointernal/database/migrations/24_create_leases_tables.up.sqlinternal/json/json_encoder.gointernal/servers/generic_server.gointernal/servers/private_leases_server.gointernal/servers/private_leases_server_test.goproto/private/osac/private/v1/event_type.protoproto/private/osac/private/v1/lease_type.protoproto/private/osac/private/v1/leases_service.proto
Summary
Leaseresource type to the private API, inspired by the Kubernetes Lease concept. Thisis a coordination primitive that will be used to implement leader election for the controller,
allowing multiple instances to run while only one actively reconciles.
Leasemessage has aLeaseSpecwith fields for holder identity, lease duration (usinggoogle.protobuf.Duration), acquire and renew timestamps, and a transition counter.LeasesgRPC service provides standard CRUD plus Signal operations with HTTP annotationson
/api/private/v1/leases.Included changes:
lease_type.protoandleases_service.proto.buf generate.Leaseadded to theEventoneof payload inevent_type.proto.24_create_leases_tables.up.sql.PrivateLeasesServerimplementation delegating toGenericServer.start_grpc_server_cmd.go.Leasecase inGenericServer.setPayloadfor event notifications.google.protobuf.Durationin the custom JSON encoder.Test plan
ginkgo run -r internalpasses (all 34 suites, including 11 new lease server tests).buf lintpasses.go build ./...succeeds.Summary by CodeRabbit