Skip to content

Commit ea9081d

Browse files
authored
Return registered groups from API (#1444)
1 parent ae5e251 commit ea9081d

File tree

4 files changed

+74
-52
lines changed

4 files changed

+74
-52
lines changed

cmd/thv/app/client.go

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -215,54 +215,36 @@ func clientRemoveCmdFunc(cmd *cobra.Command, args []string) error {
215215
}
216216

217217
func listRegisteredClientsCmdFunc(cmd *cobra.Command, _ []string) error {
218-
cfg := config.GetConfig()
219-
220-
// Check if we have groups configured
221-
groupManager, err := groups.NewManager()
218+
clientManager, err := client.NewManager(cmd.Context())
222219
if err != nil {
223-
return fmt.Errorf("failed to create group manager: %w", err)
220+
return fmt.Errorf("failed to create client manager: %w", err)
224221
}
225222

226-
allGroups, err := groupManager.List(cmd.Context())
223+
registeredClients, err := clientManager.ListClients(cmd.Context())
227224
if err != nil {
228-
return fmt.Errorf("failed to list groups: %w", err)
225+
return fmt.Errorf("failed to list registered clients: %w", err)
229226
}
230227

231-
hasGroups := len(allGroups) > 0
232-
clientGroups := make(map[string][]string) // client -> groups
233-
allRegisteredClients := make(map[string]bool)
234-
235-
if hasGroups {
236-
// Collect clients from all groups
237-
for _, group := range allGroups {
238-
for _, clientName := range group.RegisteredClients {
239-
allRegisteredClients[clientName] = true
240-
clientGroups[clientName] = append(clientGroups[clientName], group.Name)
241-
}
242-
}
243-
}
244-
245-
// Add clients from global config that might not be in any group
246-
for _, clientName := range cfg.Clients.RegisteredClients {
247-
if !allRegisteredClients[clientName] {
248-
allRegisteredClients[clientName] = true
249-
if hasGroups {
250-
clientGroups[clientName] = []string{} // no groups
251-
}
228+
// Convert to UI format
229+
var uiClients []ui.RegisteredClient
230+
for _, regClient := range registeredClients {
231+
uiClient := ui.RegisteredClient{
232+
Name: string(regClient.Name),
233+
Groups: regClient.Groups,
252234
}
235+
uiClients = append(uiClients, uiClient)
253236
}
254237

255-
// Convert to slice for table rendering
256-
var registeredClients []ui.RegisteredClient
257-
for clientName := range allRegisteredClients {
258-
registered := ui.RegisteredClient{
259-
Name: clientName,
260-
Groups: clientGroups[clientName],
238+
// Determine if we have groups by checking if any client has groups
239+
hasGroups := false
240+
for _, regClient := range registeredClients {
241+
if len(regClient.Groups) > 0 {
242+
hasGroups = true
243+
break
261244
}
262-
registeredClients = append(registeredClients, registered)
263245
}
264246

265-
return ui.RenderRegisteredClientsTable(registeredClients, hasGroups)
247+
return ui.RenderRegisteredClientsTable(uiClients, hasGroups)
266248
}
267249

268250
func performClientRegistration(ctx context.Context, clients []client.Client, groupNames []string) error {

pkg/api/v1/clients.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ func ClientRouter(
5151
// @Description List all registered clients in ToolHive
5252
// @Tags clients
5353
// @Produce json
54-
// @Success 200 {array} client.Client
54+
// @Success 200 {array} client.RegisteredClient
5555
// @Router /api/v1beta/clients [get]
56-
func (c *ClientRoutes) listClients(w http.ResponseWriter, _ *http.Request) {
57-
clients, err := c.clientManager.ListClients()
56+
func (c *ClientRoutes) listClients(w http.ResponseWriter, r *http.Request) {
57+
clients, err := c.clientManager.ListClients(r.Context())
5858
if err != nil {
5959
logger.Errorf("Failed to list clients: %v", err)
6060
http.Error(w, "Failed to list clients", http.StatusInternalServerError)

pkg/client/manager.go

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,18 @@ type Client struct {
2222
Name MCPClient `json:"name"`
2323
}
2424

25+
// RegisteredClient represents a registered client with its associated groups.
26+
type RegisteredClient struct {
27+
Name MCPClient `json:"name"`
28+
Groups []string `json:"groups"`
29+
}
30+
2531
// Manager is the interface for managing registered ToolHive clients.
2632
//
2733
//go:generate mockgen -destination=mocks/mock_manager.go -package=mocks -source=manager.go Manager
2834
type Manager interface {
29-
// ListClients returns a list of all registered.
30-
ListClients() ([]Client, error)
35+
// ListClients returns a list of all registered clients with their group information.
36+
ListClients(ctx context.Context) ([]RegisteredClient, error)
3137
// RegisterClients registers multiple clients with ToolHive for the specified workloads.
3238
RegisterClients(clients []Client, workloads []core.Workload) error
3339
// UnregisterClients unregisters multiple clients from ToolHive for the specified workloads.
@@ -61,15 +67,49 @@ func NewManager(ctx context.Context) (Manager, error) {
6167
}, nil
6268
}
6369

64-
func (*defaultManager) ListClients() ([]Client, error) {
65-
clients := []Client{}
66-
appConfig := config.GetConfig()
70+
func (m *defaultManager) ListClients(ctx context.Context) ([]RegisteredClient, error) {
71+
cfg := config.GetConfig()
72+
73+
// Get all groups
74+
allGroups, err := m.groupManager.List(ctx)
75+
if err != nil {
76+
return nil, fmt.Errorf("failed to list groups: %w", err)
77+
}
78+
79+
clientGroups := make(map[string][]string) // client -> groups
80+
allRegisteredClients := make(map[string]bool)
81+
82+
if len(allGroups) > 0 {
83+
// Collect clients from all groups
84+
for _, group := range allGroups {
85+
for _, clientName := range group.RegisteredClients {
86+
allRegisteredClients[clientName] = true
87+
clientGroups[clientName] = append(clientGroups[clientName], group.Name)
88+
}
89+
}
90+
}
91+
92+
// Add clients from global config that might not be in any group
93+
for _, clientName := range cfg.Clients.RegisteredClients {
94+
if !allRegisteredClients[clientName] {
95+
allRegisteredClients[clientName] = true
96+
if len(allGroups) > 0 {
97+
clientGroups[clientName] = []string{} // no groups
98+
}
99+
}
100+
}
67101

68-
for _, clientName := range appConfig.Clients.RegisteredClients {
69-
clients = append(clients, Client{Name: MCPClient(clientName)})
102+
// Convert to slice for return
103+
var registeredClients []RegisteredClient
104+
for clientName := range allRegisteredClients {
105+
registered := RegisteredClient{
106+
Name: MCPClient(clientName),
107+
Groups: clientGroups[clientName],
108+
}
109+
registeredClients = append(registeredClients, registered)
70110
}
71111

72-
return clients, nil
112+
return registeredClients, nil
73113
}
74114

75115
// RegisterClients registers multiple clients with ToolHive for the specified workloads.

pkg/client/mocks/mock_manager.go

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)