Fix compilation errors from SearchServer extraction

- Update NewLocalResourceClient to accept SearchServer parameter
- Add SearchClient methods to ResourceClient interface (client needs both)
- Fix directResourceClient to implement new interface with stub methods
- Update search_and_storage.go test to create SearchServer separately

This continues the work of extracting SearchServer from ResourceServer
to enable independent usage by storage.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
mayor
2026-01-12 17:59:46 +01:00
committed by Rafael Paulovic
co-authored by Claude Opus 4.5
parent c8f1efe7c7
commit 4913baaf04
3 changed files with 66 additions and 32 deletions
+17 -15
View File
@@ -38,10 +38,10 @@ func (d *directResourceClient) GetBlob(ctx context.Context, in *resourcepb.GetBl
return d.server.GetBlob(ctx, in)
}
//// GetStats implements ResourceClient.
//func (d *directResourceClient) GetStats(ctx context.Context, in *resourcepb.ResourceStatsRequest, opts ...grpc.CallOption) (*resourcepb.ResourceStatsResponse, error) {
// return d.server.GetStats(ctx, in)
//}
// GetStats implements ResourceClient (SearchClient).
func (d *directResourceClient) GetStats(ctx context.Context, in *resourcepb.ResourceStatsRequest, opts ...grpc.CallOption) (*resourcepb.ResourceStatsResponse, error) {
return nil, fmt.Errorf("GetStats not supported with direct resource client")
}
// IsHealthy implements ResourceClient.
func (d *directResourceClient) IsHealthy(ctx context.Context, in *resourcepb.HealthCheckRequest, opts ...grpc.CallOption) (*resourcepb.HealthCheckResponse, error) {
@@ -53,13 +53,15 @@ func (d *directResourceClient) List(ctx context.Context, in *resourcepb.ListRequ
return d.server.List(ctx, in)
}
//func (d *directResourceClient) ListManagedObjects(ctx context.Context, in *resourcepb.ListManagedObjectsRequest, opts ...grpc.CallOption) (*resourcepb.ListManagedObjectsResponse, error) {
// return d.server.ListManagedObjects(ctx, in)
//}
//
//func (d *directResourceClient) CountManagedObjects(ctx context.Context, in *resourcepb.CountManagedObjectsRequest, opts ...grpc.CallOption) (*resourcepb.CountManagedObjectsResponse, error) {
// return d.server.CountManagedObjects(ctx, in)
//}
// ListManagedObjects implements ResourceClient (SearchClient).
func (d *directResourceClient) ListManagedObjects(ctx context.Context, in *resourcepb.ListManagedObjectsRequest, opts ...grpc.CallOption) (*resourcepb.ListManagedObjectsResponse, error) {
return nil, fmt.Errorf("ListManagedObjects not supported with direct resource client")
}
// CountManagedObjects implements ResourceClient (SearchClient).
func (d *directResourceClient) CountManagedObjects(ctx context.Context, in *resourcepb.CountManagedObjectsRequest, opts ...grpc.CallOption) (*resourcepb.CountManagedObjectsResponse, error) {
return nil, fmt.Errorf("CountManagedObjects not supported with direct resource client")
}
// PutBlob implements ResourceClient.
func (d *directResourceClient) PutBlob(ctx context.Context, in *resourcepb.PutBlobRequest, opts ...grpc.CallOption) (*resourcepb.PutBlobResponse, error) {
@@ -71,10 +73,10 @@ func (d *directResourceClient) Read(ctx context.Context, in *resourcepb.ReadRequ
return d.server.Read(ctx, in)
}
// Search implements ResourceClient.
//func (d *directResourceClient) Search(ctx context.Context, in *resourcepb.ResourceSearchRequest, opts ...grpc.CallOption) (*resourcepb.ResourceSearchResponse, error) {
// return d.server.Search(ctx, in)
//}
// Search implements ResourceClient (SearchClient).
func (d *directResourceClient) Search(ctx context.Context, in *resourcepb.ResourceSearchRequest, opts ...grpc.CallOption) (*resourcepb.ResourceSearchResponse, error) {
return nil, fmt.Errorf("Search not supported with direct resource client")
}
// Update implements ResourceClient.
func (d *directResourceClient) Update(ctx context.Context, in *resourcepb.UpdateRequest, opts ...grpc.CallOption) (*resourcepb.UpdateResponse, error) {
+23 -2
View File
@@ -43,6 +43,8 @@ type ResourceClient interface {
resourcepb.BlobStoreClient
resourcepb.DiagnosticsClient
resourcepb.QuotasClient
// SearchClient methods are included for convenience - the client typically needs both
SearchClient
}
// Internal implementation
@@ -95,9 +97,10 @@ func NewLegacyResourceClient(channel grpc.ClientConnInterface, indexChannel grpc
return newResourceClient(cc, cci)
}
func NewLocalResourceClient(server ResourceServer) ResourceClient {
func NewLocalResourceClient(server ResourceServer, searchServer SearchServer) ResourceClient {
// scenario: local in-proc
channel := &inprocgrpc.Channel{}
indexChannel := &inprocgrpc.Channel{}
tracer := otel.Tracer("github.com/grafana/grafana/pkg/storage/unified/resource")
grpcAuthInt := grpcutils.NewUnsafeAuthenticator(tracer)
@@ -118,13 +121,31 @@ func NewLocalResourceClient(server ResourceServer) ResourceClient {
)
}
// Register search services on the index channel if searchServer is provided
if searchServer != nil {
for _, desc := range []*grpc.ServiceDesc{
&resourcepb.ResourceIndex_ServiceDesc,
&resourcepb.ManagedObjectIndex_ServiceDesc,
} {
indexChannel.RegisterService(
grpchan.InterceptServer(
desc,
grpcAuth.UnaryServerInterceptor(grpcAuthInt),
grpcAuth.StreamServerInterceptor(grpcAuthInt),
),
searchServer,
)
}
}
clientInt := authnlib.NewGrpcClientInterceptor(
ProvideInProcExchanger(),
authnlib.WithClientInterceptorIDTokenExtractor(idTokenExtractor),
)
cc := grpchan.InterceptClientConn(channel, clientInt.UnaryClientInterceptor, clientInt.StreamClientInterceptor)
return newResourceClient(cc, cc)
cci := grpchan.InterceptClientConn(indexChannel, clientInt.UnaryClientInterceptor, clientInt.StreamClientInterceptor)
return newResourceClient(cc, cci)
}
type RemoteResourceClientConfig struct {
@@ -32,6 +32,7 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
nsPrefix := "test-ns"
var server resource.ResourceServer
var searchServer resource.SearchServer
t.Run("Create initial resources in storage", func(t *testing.T) {
initialResources := []struct {
@@ -96,25 +97,35 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
})
t.Run("Create a resource server with both backends", func(t *testing.T) {
// Create a resource server with both backends
// Create search server first
var err error
server, err = resource.NewResourceServer(resource.ResourceServerOptions{
Backend: backend,
Search: resource.SearchOptions{
Backend: searchBackend,
Resources: &resource.TestDocumentBuilderSupplier{
GroupsResources: map[string]string{
"test.grafana.app": "testresources",
},
searchOpts := resource.SearchOptions{
Backend: searchBackend,
Resources: &resource.TestDocumentBuilderSupplier{
GroupsResources: map[string]string{
"test.grafana.app": "testresources",
},
},
}
searchServer, err = resource.NewSearchServer(searchOpts, backend, nil, nil, nil, nil)
require.NoError(t, err)
require.NotNil(t, searchServer)
// Initialize the search server
err = searchServer.Init(ctx)
require.NoError(t, err)
// Create a resource server with the search server
server, err = resource.NewResourceServer(resource.ResourceServerOptions{
Backend: backend,
Search: searchServer,
})
require.NoError(t, err)
})
t.Run("Search for initial resources", func(t *testing.T) {
// Test 1: Search for initial resources
searchResp, err := server.Search(ctx, &resourcepb.ResourceSearchRequest{
searchResp, err := searchServer.Search(ctx, &resourcepb.ResourceSearchRequest{
Options: &resourcepb.ListOptions{
Key: &resourcepb.ResourceKey{
Group: "test.grafana.app",
@@ -194,7 +205,7 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
})
t.Run("Search for documents", func(t *testing.T) {
searchResp, err := server.Search(ctx, &resourcepb.ResourceSearchRequest{
searchResp, err := searchServer.Search(ctx, &resourcepb.ResourceSearchRequest{
Options: &resourcepb.ListOptions{
Key: &resourcepb.ResourceKey{
Group: "test.grafana.app",
@@ -212,7 +223,7 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
})
t.Run("Search with tags", func(t *testing.T) {
searchResp, err := server.Search(ctx, &resourcepb.ResourceSearchRequest{
searchResp, err := searchServer.Search(ctx, &resourcepb.ResourceSearchRequest{
Options: &resourcepb.ListOptions{
Key: &resourcepb.ResourceKey{
Group: "test.grafana.app",
@@ -231,7 +242,7 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
require.Equal(t, int64(0), searchResp.TotalHits)
// this is the correct way of searching by tag
searchResp, err = server.Search(ctx, &resourcepb.ResourceSearchRequest{
searchResp, err = searchServer.Search(ctx, &resourcepb.ResourceSearchRequest{
Options: &resourcepb.ListOptions{
Key: &resourcepb.ResourceKey{
Group: "test.grafana.app",
@@ -253,7 +264,7 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
})
t.Run("Search with specific tag", func(t *testing.T) {
searchResp, err := server.Search(ctx, &resourcepb.ResourceSearchRequest{
searchResp, err := searchServer.Search(ctx, &resourcepb.ResourceSearchRequest{
Options: &resourcepb.ListOptions{
Key: &resourcepb.ResourceKey{
Group: "test.grafana.app",
@@ -272,7 +283,7 @@ func RunTestSearchAndStorage(t *testing.T, ctx context.Context, backend resource
require.Equal(t, int64(0), searchResp.TotalHits)
// this is the correct way of searching by tag
searchResp, err = server.Search(ctx, &resourcepb.ResourceSearchRequest{
searchResp, err = searchServer.Search(ctx, &resourcepb.ResourceSearchRequest{
Options: &resourcepb.ListOptions{
Key: &resourcepb.ResourceKey{
Group: "test.grafana.app",