Skip to content

Commit ce74cac

Browse files
committed
introduced ServerRegistry type and converter functions.
Signed-off-by: Daniele Martinoli <dmartino@redhat.com>
1 parent 16cc6e5 commit ce74cac

27 files changed

+922
-359
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/onsi/gomega v1.38.2
1313
github.com/spf13/viper v1.21.0
1414
github.com/sqlc-dev/pqtype v0.3.0
15-
github.com/stacklok/toolhive v0.6.2
15+
github.com/stacklok/toolhive v0.6.3-0.20251111071910-8739ec42d905
1616
github.com/stretchr/testify v1.11.1
1717
github.com/swaggo/swag/v2 v2.0.0-rc4
1818
go.uber.org/mock v0.6.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
203203
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
204204
github.com/sqlc-dev/pqtype v0.3.0 h1:b09TewZ3cSnO5+M1Kqq05y0+OjqIptxELaSayg7bmqk=
205205
github.com/sqlc-dev/pqtype v0.3.0/go.mod h1:oyUjp5981ctiL9UYvj1bVvCKi8OXkCa0u645hce7CAs=
206-
github.com/stacklok/toolhive v0.6.2 h1:r47V8z2rv4lTAOOaSMsDVLqHPCuX7jAK5/l9wsY80rs=
207-
github.com/stacklok/toolhive v0.6.2/go.mod h1:TfYC6y/NMiC04GuMe5GdSMp59u7sUZ4ElFz4uSleg3M=
206+
github.com/stacklok/toolhive v0.6.3-0.20251111071910-8739ec42d905 h1:QcZm42D+Fu+7sUmZPUDNInjyya9ic5Ccl6zKYb6z2i4=
207+
github.com/stacklok/toolhive v0.6.3-0.20251111071910-8739ec42d905/go.mod h1:U6T5FqLzlwE+s4Ccp0lXvZbjX/SwG3YjVMYmSaSWPKU=
208208
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
209209
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
210210
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=

internal/api/v0/routes.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
"github.com/go-chi/chi/v5"
1111
"github.com/stacklok/toolhive/pkg/logger"
12-
"github.com/stacklok/toolhive/pkg/registry"
12+
toolhivetypes "github.com/stacklok/toolhive/pkg/registry/types"
1313
"github.com/stacklok/toolhive/pkg/versions"
1414
"gopkg.in/yaml.v3"
1515

@@ -335,7 +335,7 @@ func (rr *Routes) listDeployedServers(w http.ResponseWriter, r *http.Request) {
335335
}
336336

337337
// newServerSummaryResponse creates a ServerSummaryResponse from server metadata
338-
func newServerSummaryResponse(server registry.ServerMetadata) ServerSummaryResponse {
338+
func newServerSummaryResponse(server toolhivetypes.ServerMetadata) ServerSummaryResponse {
339339
return ServerSummaryResponse{
340340
Name: server.GetName(),
341341
Description: server.GetDescription(),
@@ -347,7 +347,7 @@ func newServerSummaryResponse(server registry.ServerMetadata) ServerSummaryRespo
347347
}
348348

349349
// newServerDetailResponse creates a ServerDetailResponse from server metadata with all available fields
350-
func newServerDetailResponse(server registry.ServerMetadata) ServerDetailResponse {
350+
func newServerDetailResponse(server toolhivetypes.ServerMetadata) ServerDetailResponse {
351351
response := ServerDetailResponse{
352352
Name: server.GetName(),
353353
Description: server.GetDescription(),
@@ -367,7 +367,7 @@ func newServerDetailResponse(server registry.ServerMetadata) ServerDetailRespons
367367
}
368368

369369
// populateEnvVars converts and populates environment variables in the response
370-
func populateEnvVars(response *ServerDetailResponse, server registry.ServerMetadata) {
370+
func populateEnvVars(response *ServerDetailResponse, server toolhivetypes.ServerMetadata) {
371371
envVars := server.GetEnvVars()
372372
if envVars == nil {
373373
return
@@ -388,7 +388,7 @@ func populateEnvVars(response *ServerDetailResponse, server registry.ServerMetad
388388
}
389389

390390
// populateMetadata converts and populates metadata in the response
391-
func populateMetadata(response *ServerDetailResponse, server registry.ServerMetadata) {
391+
func populateMetadata(response *ServerDetailResponse, server toolhivetypes.ServerMetadata) {
392392
// Convert metadata from *Metadata to map[string]interface{}
393393
if metadata := server.GetMetadata(); metadata != nil {
394394
response.Metadata = map[string]interface{}{
@@ -410,7 +410,7 @@ func populateMetadata(response *ServerDetailResponse, server registry.ServerMeta
410410
}
411411

412412
// populateServerTypeSpecificFields populates fields specific to container or remote servers
413-
func populateServerTypeSpecificFields(response *ServerDetailResponse, server registry.ServerMetadata) {
413+
func populateServerTypeSpecificFields(response *ServerDetailResponse, server toolhivetypes.ServerMetadata) {
414414
if !server.IsRemote() {
415415
populateContainerServerFields(response, server)
416416
} else {
@@ -419,12 +419,12 @@ func populateServerTypeSpecificFields(response *ServerDetailResponse, server reg
419419
}
420420

421421
// populateContainerServerFields populates fields specific to container servers (ImageMetadata)
422-
func populateContainerServerFields(response *ServerDetailResponse, server registry.ServerMetadata) {
422+
func populateContainerServerFields(response *ServerDetailResponse, server toolhivetypes.ServerMetadata) {
423423
// The server might be wrapped in a serverWithName struct from the service layer
424424
actualServer := extractEmbeddedServerMetadata(server)
425425

426426
// Type assert to access ImageMetadata-specific fields
427-
imgMetadata, ok := actualServer.(*registry.ImageMetadata)
427+
imgMetadata, ok := actualServer.(*toolhivetypes.ImageMetadata)
428428
if !ok {
429429
return
430430
}
@@ -453,11 +453,11 @@ func populateContainerServerFields(response *ServerDetailResponse, server regist
453453
}
454454

455455
// populateRemoteServerFields populates fields specific to remote servers
456-
func populateRemoteServerFields(response *ServerDetailResponse, server registry.ServerMetadata) {
456+
func populateRemoteServerFields(response *ServerDetailResponse, server toolhivetypes.ServerMetadata) {
457457
// The server might be wrapped in a serverWithName struct from the service layer
458458
actualServer := extractEmbeddedServerMetadata(server)
459459

460-
remoteMetadata, ok := actualServer.(*registry.RemoteServerMetadata)
460+
remoteMetadata, ok := actualServer.(*toolhivetypes.RemoteServerMetadata)
461461
if !ok {
462462
return
463463
}
@@ -474,7 +474,7 @@ func populateRemoteServerFields(response *ServerDetailResponse, server registry.
474474
}
475475

476476
// extractEmbeddedServerMetadata extracts the embedded ServerMetadata from serverWithName wrapper
477-
func extractEmbeddedServerMetadata(server registry.ServerMetadata) registry.ServerMetadata {
477+
func extractEmbeddedServerMetadata(server toolhivetypes.ServerMetadata) toolhivetypes.ServerMetadata {
478478
// Use reflection to check if this is a struct with an embedded ServerMetadata field
479479
v := reflect.ValueOf(server)
480480
if v.Kind() == reflect.Ptr {
@@ -489,7 +489,7 @@ func extractEmbeddedServerMetadata(server registry.ServerMetadata) registry.Serv
489489

490490
// Check if it's an embedded field (Anonymous) that implements ServerMetadata
491491
if fieldType.Anonymous && field.CanInterface() {
492-
if serverMetadata, ok := field.Interface().(registry.ServerMetadata); ok {
492+
if serverMetadata, ok := field.Interface().(toolhivetypes.ServerMetadata); ok {
493493
return serverMetadata
494494
}
495495
}
@@ -671,12 +671,12 @@ func serveOpenAPIYAML(w http.ResponseWriter, _ *http.Request) {
671671

672672
// NewServerSummaryResponseForTesting creates a ServerSummaryResponse for testing
673673
// Deprecated: Use API v0.1 instead
674-
func NewServerSummaryResponseForTesting(server registry.ServerMetadata) ServerSummaryResponse {
674+
func NewServerSummaryResponseForTesting(server toolhivetypes.ServerMetadata) ServerSummaryResponse {
675675
return newServerSummaryResponse(server)
676676
}
677677

678678
// NewServerDetailResponseForTesting creates a ServerDetailResponse for testing
679679
// Deprecated: Use API v0.1 instead
680-
func NewServerDetailResponseForTesting(server registry.ServerMetadata) ServerDetailResponse {
680+
func NewServerDetailResponseForTesting(server toolhivetypes.ServerMetadata) ServerDetailResponse {
681681
return newServerDetailResponse(server)
682682
}

internal/api/v0/routes_test.go

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"testing"
99
"time"
1010

11-
"github.com/stacklok/toolhive/pkg/registry"
11+
toolhivetypes "github.com/stacklok/toolhive/pkg/registry/types"
1212
"github.com/stretchr/testify/assert"
1313
"github.com/stretchr/testify/require"
1414
"go.uber.org/mock/gomock"
@@ -233,12 +233,12 @@ const testRegistryJSON = `{
233233

234234
// realisticRegistryProvider implements RegistryDataProvider for testing with our realistic test data
235235
type realisticRegistryProvider struct {
236-
data *registry.Registry
236+
data *toolhivetypes.Registry
237237
}
238238

239239
// newRealisticRegistryProvider creates a provider with our representative test data
240240
func newRealisticRegistryProvider() (*realisticRegistryProvider, error) {
241-
var data registry.Registry
241+
var data toolhivetypes.Registry
242242
if err := json.Unmarshal([]byte(testRegistryJSON), &data); err != nil {
243243
return nil, err
244244
}
@@ -249,7 +249,7 @@ func newRealisticRegistryProvider() (*realisticRegistryProvider, error) {
249249
}
250250

251251
// GetRegistryData implements RegistryDataProvider.GetRegistryData
252-
func (p *realisticRegistryProvider) GetRegistryData(_ context.Context) (*registry.Registry, error) {
252+
func (p *realisticRegistryProvider) GetRegistryData(_ context.Context) (*toolhivetypes.Registry, error) {
253253
return p.data, nil
254254
}
255255

@@ -321,14 +321,14 @@ func TestRegistryRouter(t *testing.T) {
321321

322322
mockSvc := mocks.NewMockRegistryService(ctrl)
323323
// Set up expectations for all routes
324-
mockSvc.EXPECT().GetRegistry(gomock.Any()).Return(&registry.Registry{
324+
mockSvc.EXPECT().GetRegistry(gomock.Any()).Return(&toolhivetypes.Registry{
325325
Version: "1.0.0",
326326
LastUpdated: time.Now().Format(time.RFC3339),
327-
Servers: make(map[string]*registry.ImageMetadata),
327+
Servers: make(map[string]*toolhivetypes.ImageMetadata),
328328
}, "test", nil).AnyTimes()
329-
mockSvc.EXPECT().ListServers(gomock.Any()).Return([]registry.ServerMetadata{}, nil).AnyTimes()
330-
mockSvc.EXPECT().GetServer(gomock.Any(), "test-server").Return(&registry.ImageMetadata{
331-
BaseServerMetadata: registry.BaseServerMetadata{
329+
mockSvc.EXPECT().ListServers(gomock.Any()).Return([]toolhivetypes.ServerMetadata{}, nil).AnyTimes()
330+
mockSvc.EXPECT().GetServer(gomock.Any(), "test-server").Return(&toolhivetypes.ImageMetadata{
331+
BaseServerMetadata: toolhivetypes.BaseServerMetadata{
332332
Name: "test-server",
333333
},
334334
}, nil).AnyTimes()
@@ -402,7 +402,7 @@ func TestListServers_FormatParameter(t *testing.T) {
402402

403403
mockSvc := mocks.NewMockRegistryService(ctrl)
404404
// Expect successful calls for toolhive format only
405-
mockSvc.EXPECT().ListServers(gomock.Any()).Return([]registry.ServerMetadata{}, nil).Times(2) // default and explicit toolhive
405+
mockSvc.EXPECT().ListServers(gomock.Any()).Return([]toolhivetypes.ServerMetadata{}, nil).Times(2) // default and explicit toolhive
406406

407407
router := v0.Router(mockSvc)
408408

@@ -481,14 +481,14 @@ func TestNewServer(t *testing.T) {
481481

482482
// Set up expectations for all test routes
483483
mockSvc.EXPECT().CheckReadiness(gomock.Any()).Return(nil).AnyTimes()
484-
mockSvc.EXPECT().GetRegistry(gomock.Any()).Return(&registry.Registry{
484+
mockSvc.EXPECT().GetRegistry(gomock.Any()).Return(&toolhivetypes.Registry{
485485
Version: "1.0.0",
486486
LastUpdated: time.Now().Format(time.RFC3339),
487-
Servers: make(map[string]*registry.ImageMetadata),
487+
Servers: make(map[string]*toolhivetypes.ImageMetadata),
488488
}, "test", nil).AnyTimes()
489-
mockSvc.EXPECT().ListServers(gomock.Any()).Return([]registry.ServerMetadata{}, nil).AnyTimes()
490-
mockSvc.EXPECT().GetServer(gomock.Any(), "test").Return(&registry.ImageMetadata{
491-
BaseServerMetadata: registry.BaseServerMetadata{
489+
mockSvc.EXPECT().ListServers(gomock.Any()).Return([]toolhivetypes.ServerMetadata{}, nil).AnyTimes()
490+
mockSvc.EXPECT().GetServer(gomock.Any(), "test").Return(&toolhivetypes.ImageMetadata{
491+
BaseServerMetadata: toolhivetypes.BaseServerMetadata{
492492
Name: "test",
493493
},
494494
}, nil).AnyTimes()
@@ -588,12 +588,12 @@ func TestNewServer_WithMiddleware(t *testing.T) {
588588

589589
// fileBasedRegistryProvider implements RegistryDataProvider for testing with embedded registry data
590590
type fileBasedRegistryProvider struct {
591-
data *registry.Registry
591+
data *toolhivetypes.Registry
592592
}
593593

594594
// newFileBasedRegistryProvider creates a new provider with embedded registry data
595595
func newFileBasedRegistryProvider() (*fileBasedRegistryProvider, error) {
596-
var data registry.Registry
596+
var data toolhivetypes.Registry
597597
if err := json.Unmarshal([]byte(testRegistryJSON), &data); err != nil {
598598
return nil, err
599599
}
@@ -604,7 +604,7 @@ func newFileBasedRegistryProvider() (*fileBasedRegistryProvider, error) {
604604
}
605605

606606
// GetRegistryData implements RegistryDataProvider.GetRegistryData
607-
func (p *fileBasedRegistryProvider) GetRegistryData(_ context.Context) (*registry.Registry, error) {
607+
func (p *fileBasedRegistryProvider) GetRegistryData(_ context.Context) (*toolhivetypes.Registry, error) {
608608
return p.data, nil
609609
}
610610

@@ -619,11 +619,11 @@ func (*fileBasedRegistryProvider) GetRegistryName() string {
619619
}
620620

621621
// Helper functions for testing the response conversion functions
622-
func newServerSummaryResponseForTesting(server registry.ServerMetadata) v0.ServerSummaryResponse {
622+
func newServerSummaryResponseForTesting(server toolhivetypes.ServerMetadata) v0.ServerSummaryResponse {
623623
return v0.NewServerSummaryResponseForTesting(server)
624624
}
625625

626-
func newServerDetailResponseForTesting(server registry.ServerMetadata) v0.ServerDetailResponse {
626+
func newServerDetailResponseForTesting(server toolhivetypes.ServerMetadata) v0.ServerDetailResponse {
627627
return v0.NewServerDetailResponseForTesting(server)
628628
}
629629

@@ -1396,8 +1396,8 @@ func TestHelperFunctions(t *testing.T) {
13961396
t.Parallel()
13971397

13981398
// Test data setup
1399-
testImageMetadata := &registry.ImageMetadata{
1400-
BaseServerMetadata: registry.BaseServerMetadata{
1399+
testImageMetadata := &toolhivetypes.ImageMetadata{
1400+
BaseServerMetadata: toolhivetypes.BaseServerMetadata{
14011401
Name: "test-server",
14021402
Description: "Test server",
14031403
Tier: "Community",
@@ -1408,8 +1408,8 @@ func TestHelperFunctions(t *testing.T) {
14081408
Image: "test-image:latest",
14091409
}
14101410

1411-
testRemoteMetadata := &registry.RemoteServerMetadata{
1412-
BaseServerMetadata: registry.BaseServerMetadata{
1411+
testRemoteMetadata := &toolhivetypes.RemoteServerMetadata{
1412+
BaseServerMetadata: toolhivetypes.BaseServerMetadata{
14131413
Name: "remote-server",
14141414
Description: "Remote test server",
14151415
Tier: "Official",
@@ -1522,7 +1522,7 @@ func TestErrorScenarios(t *testing.T) {
15221522
t.Parallel()
15231523
// This test needs its own mock since it calls ListServers (chi routes /servers/ to list endpoint)
15241524
emptyNameMockSvc := mocks.NewMockRegistryService(ctrl)
1525-
emptyNameMockSvc.EXPECT().ListServers(gomock.Any()).Return([]registry.ServerMetadata{}, nil)
1525+
emptyNameMockSvc.EXPECT().ListServers(gomock.Any()).Return([]toolhivetypes.ServerMetadata{}, nil)
15261526

15271527
router := v0.Router(emptyNameMockSvc)
15281528

internal/service/file_provider.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"context"
66
"fmt"
77

8-
"github.com/stacklok/toolhive/pkg/registry"
8+
toolhivetypes "github.com/stacklok/toolhive/pkg/registry/types"
99

1010
"github.com/stacklok/toolhive-registry-server/pkg/config"
1111
"github.com/stacklok/toolhive-registry-server/pkg/sources"
@@ -34,9 +34,24 @@ func NewFileRegistryDataProvider(storageManager sources.StorageManager, cfg *con
3434
// GetRegistryData implements RegistryDataProvider.GetRegistryData.
3535
// It delegates to the StorageManager to retrieve and parse registry data.
3636
// This eliminates code duplication and provides a single source of truth for file operations.
37-
func (p *FileRegistryDataProvider) GetRegistryData(ctx context.Context) (*registry.Registry, error) {
38-
// Delegate to storage manager - all file reading logic is centralized there
39-
return p.storageManager.Get(ctx, p.config)
37+
//
38+
// NOTE: In PR 1, StorageManager returns ServerRegistry but RegistryDataProvider interface
39+
// still expects toolhive Registry. This method converts at the boundary to maintain
40+
// backward compatibility until PR 2.
41+
func (p *FileRegistryDataProvider) GetRegistryData(ctx context.Context) (*toolhivetypes.Registry, error) {
42+
// Get ServerRegistry from storage manager (new format)
43+
serverReg, err := p.storageManager.Get(ctx, p.config)
44+
if err != nil {
45+
return nil, fmt.Errorf("failed to get registry data: %w", err)
46+
}
47+
48+
// Convert ServerRegistry → ToolHive Registry using ToToolhive() method
49+
toolhiveReg, err := serverReg.ToToolhive()
50+
if err != nil {
51+
return nil, fmt.Errorf("failed to convert to toolhive format: %w", err)
52+
}
53+
54+
return toolhiveReg, nil
4055
}
4156

4257
// GetSource implements RegistryDataProvider.GetSource.

0 commit comments

Comments
 (0)