Skip to content

Commit d31feb5

Browse files
authored
Remove group label from workload (#1173)
1 parent 250b078 commit d31feb5

File tree

10 files changed

+95
-150
lines changed

10 files changed

+95
-150
lines changed

cmd/thv/app/run.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,9 @@ func runCmdFunc(cmd *cobra.Command, args []string) error {
8080
// Get debug mode flag
8181
debugMode, _ := cmd.Flags().GetBool("debug")
8282

83-
// Build the run configuration
84-
runnerConfig, err := BuildRunnerConfig(ctx, &runFlags, serverOrImage, cmdArgs, debugMode, cmd)
85-
if err != nil {
86-
return err
83+
workloadName := runFlags.Name
84+
if workloadName == "" {
85+
workloadName = serverOrImage
8786
}
8887

8988
if runFlags.Group != "" {
@@ -93,12 +92,12 @@ func runCmdFunc(cmd *cobra.Command, args []string) error {
9392
}
9493

9594
// Check if the workload is already in a group
96-
group, err := groupManager.GetWorkloadGroup(ctx, runFlags.Name)
95+
group, err := groupManager.GetWorkloadGroup(ctx, workloadName)
9796
if err != nil {
9897
return fmt.Errorf("failed to get workload group: %v", err)
9998
}
10099
if group != nil && group.Name != runFlags.Group {
101-
return fmt.Errorf("workload '%s' is already in group '%s'", runFlags.Name, group.Name)
100+
return fmt.Errorf("workload '%s' is already in group '%s'", workloadName, group.Name)
102101
}
103102

104103
// Validate that the group specified exists
@@ -111,6 +110,12 @@ func runCmdFunc(cmd *cobra.Command, args []string) error {
111110
}
112111
}
113112

113+
// Build the run configuration
114+
runnerConfig, err := BuildRunnerConfig(ctx, &runFlags, serverOrImage, cmdArgs, debugMode, cmd)
115+
if err != nil {
116+
return err
117+
}
118+
114119
// Create container runtime
115120
rt, err := container.NewFactory().Create(ctx)
116121
if err != nil {

pkg/errors/errors.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ const (
2525
// ErrContainerAlreadyRunning is returned when a container is already running
2626
ErrContainerAlreadyRunning = "container_already_running"
2727

28+
// ErrRunConfigNotFound is returned when a run configuration is not found
29+
ErrRunConfigNotFound = "run_config_not_found"
30+
2831
// ErrTransport is returned when there is an error with the transport
2932
ErrTransport = "transport"
3033

@@ -99,6 +102,11 @@ func NewContainerAlreadyRunningError(message string, cause error) *Error {
99102
return NewError(ErrContainerAlreadyRunning, message, cause)
100103
}
101104

105+
// NewRunConfigNotFoundError creates a new run configuration not found error
106+
func NewRunConfigNotFoundError(message string, cause error) *Error {
107+
return NewError(ErrRunConfigNotFound, message, cause)
108+
}
109+
102110
// NewTransportError creates a new transport error
103111
func NewTransportError(message string, cause error) *Error {
104112
return NewError(ErrTransport, message, cause)
@@ -150,6 +158,12 @@ func IsContainerAlreadyRunning(err error) bool {
150158
return ok && e.Type == ErrContainerAlreadyRunning
151159
}
152160

161+
// IsRunConfigNotFound checks if the error is a run configuration not found error
162+
func IsRunConfigNotFound(err error) bool {
163+
e, ok := err.(*Error)
164+
return ok && e.Type == ErrRunConfigNotFound
165+
}
166+
153167
// IsTransport checks if the error is a transport error
154168
func IsTransport(err error) bool {
155169
e, ok := err.(*Error)

pkg/groups/group_test.go

Lines changed: 12 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ import (
1313

1414
"github.com/stacklok/toolhive/pkg/logger"
1515
"github.com/stacklok/toolhive/pkg/state/mocks"
16-
"github.com/stacklok/toolhive/pkg/workloads"
17-
workloadmocks "github.com/stacklok/toolhive/pkg/workloads/mocks"
1816
)
1917

2018
func init() {
@@ -103,7 +101,7 @@ func TestManager_Create(t *testing.T) {
103101
defer ctrl.Finish()
104102

105103
mockStore := mocks.NewMockStore(ctrl)
106-
manager := &manager{store: mockStore, workloadManager: nil}
104+
manager := &manager{store: mockStore}
107105

108106
// Set up mock expectations
109107
tt.setupMock(mockStore)
@@ -178,7 +176,7 @@ func TestManager_Get(t *testing.T) {
178176
defer ctrl.Finish()
179177

180178
mockStore := mocks.NewMockStore(ctrl)
181-
manager := &manager{store: mockStore, workloadManager: nil}
179+
manager := &manager{store: mockStore}
182180

183181
// Set up mock expectations
184182
tt.setupMock(mockStore)
@@ -284,7 +282,7 @@ func TestManager_List(t *testing.T) {
284282
defer ctrl.Finish()
285283

286284
mockStore := mocks.NewMockStore(ctrl)
287-
manager := &manager{store: mockStore, workloadManager: nil}
285+
manager := &manager{store: mockStore}
288286

289287
// Set up mock expectations
290288
tt.setupMock(mockStore)
@@ -370,7 +368,7 @@ func TestManager_Delete(t *testing.T) {
370368
defer ctrl.Finish()
371369

372370
mockStore := mocks.NewMockStore(ctrl)
373-
manager := &manager{store: mockStore, workloadManager: nil}
371+
manager := &manager{store: mockStore}
374372

375373
// Set up mock expectations
376374
tt.setupMock(mockStore)
@@ -444,7 +442,7 @@ func TestManager_Exists(t *testing.T) {
444442
defer ctrl.Finish()
445443

446444
mockStore := mocks.NewMockStore(ctrl)
447-
manager := &manager{store: mockStore, workloadManager: nil}
445+
manager := &manager{store: mockStore}
448446

449447
// Set up mock expectations
450448
tt.setupMock(mockStore)
@@ -469,66 +467,18 @@ func TestManager_GetWorkloadGroup(t *testing.T) {
469467
t.Parallel()
470468

471469
tests := []struct {
472-
name string
473-
workloadName string
474-
setupMock func(*mocks.MockStore)
475-
setupWorkloadManager func(*workloadmocks.MockManager)
476-
workloadGroup string // The group the workload belongs to (empty if none)
477-
expectError bool
478-
expectedGroup *Group
479-
errorMsg string
470+
name string
471+
workloadName string
472+
expectError bool
473+
expectedGroup *Group
474+
errorMsg string
480475
}{
481476
{
482-
name: "workload found in group",
483-
workloadName: "test-workload",
484-
workloadGroup: testGroupName,
485-
setupMock: func(mock *mocks.MockStore) {
486-
// Mock GetReader for the group
487-
mock.EXPECT().
488-
GetReader(gomock.Any(), testGroupName).
489-
Return(&mockReadCloser{data: `{"name":"` + testGroupName + `"}`}, nil)
490-
},
491-
setupWorkloadManager: func(mock *workloadmocks.MockManager) {
492-
// Mock GetWorkload to return a workload in a group
493-
mock.EXPECT().
494-
GetWorkload(gomock.Any(), "test-workload").
495-
Return(workloads.Workload{Name: "test-workload", Group: testGroupName}, nil)
496-
},
497-
expectError: false,
498-
expectedGroup: &Group{Name: testGroupName},
499-
},
500-
{
501-
name: "workload not found in any group",
477+
name: "workload not found",
502478
workloadName: "nonexistent-workload",
503-
workloadGroup: "",
504-
setupMock: func(_ *mocks.MockStore) {
505-
// No mock expectations needed since workload has no group
506-
},
507-
setupWorkloadManager: func(mock *workloadmocks.MockManager) {
508-
// Mock GetWorkload to return a workload with no group
509-
mock.EXPECT().
510-
GetWorkload(gomock.Any(), "nonexistent-workload").
511-
Return(workloads.Workload{Name: "nonexistent-workload", Group: ""}, nil)
512-
},
513479
expectError: false,
514480
expectedGroup: nil,
515481
},
516-
{
517-
name: "workload manager fails to get workload",
518-
workloadName: "test-workload",
519-
workloadGroup: "",
520-
setupMock: func(_ *mocks.MockStore) {
521-
// No mock expectations needed since workload manager will fail
522-
},
523-
setupWorkloadManager: func(mock *workloadmocks.MockManager) {
524-
// Mock GetWorkload to fail
525-
mock.EXPECT().
526-
GetWorkload(gomock.Any(), "test-workload").
527-
Return(workloads.Workload{}, errors.New("workload not found"))
528-
},
529-
expectError: false,
530-
expectedGroup: nil, // When workload manager fails, we return nil (not in any group)
531-
},
532482
}
533483

534484
for _, tt := range tests {
@@ -539,12 +489,7 @@ func TestManager_GetWorkloadGroup(t *testing.T) {
539489
defer ctrl.Finish()
540490

541491
mockStore := mocks.NewMockStore(ctrl)
542-
mockWorkloadManager := workloadmocks.NewMockManager(ctrl)
543-
manager := &manager{store: mockStore, workloadManager: mockWorkloadManager}
544-
545-
// Set up mock expectations
546-
tt.setupMock(mockStore)
547-
tt.setupWorkloadManager(mockWorkloadManager)
492+
manager := &manager{store: mockStore}
548493

549494
// Call the method
550495
group, err := manager.GetWorkloadGroup(context.Background(), tt.workloadName)
@@ -580,22 +525,3 @@ func (m *mockWriteCloser) Write(p []byte) (n int, err error) {
580525
func (*mockWriteCloser) Close() error {
581526
return nil
582527
}
583-
584-
// mockReadCloser implements io.ReadCloser for testing
585-
type mockReadCloser struct {
586-
data string
587-
pos int
588-
}
589-
590-
func (m *mockReadCloser) Read(p []byte) (n int, err error) {
591-
if m.pos >= len(m.data) {
592-
return 0, io.EOF
593-
}
594-
n = copy(p, m.data[m.pos:])
595-
m.pos += n
596-
return n, nil
597-
}
598-
599-
func (*mockReadCloser) Close() error {
600-
return nil
601-
}

pkg/groups/manager.go

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import (
55
"encoding/json"
66
"fmt"
77

8+
"github.com/stacklok/toolhive/pkg/errors"
9+
"github.com/stacklok/toolhive/pkg/runner"
810
"github.com/stacklok/toolhive/pkg/state"
9-
"github.com/stacklok/toolhive/pkg/workloads"
1011
)
1112

1213
// manager implements the Manager interface
1314
type manager struct {
14-
store state.Store
15-
workloadManager workloads.Manager
15+
store state.Store
1616
}
1717

1818
// NewManager creates a new group manager
@@ -22,23 +22,7 @@ func NewManager() (Manager, error) {
2222
return nil, fmt.Errorf("failed to create group state store: %w", err)
2323
}
2424

25-
workloadManager, err := workloads.NewManager(context.Background())
26-
if err != nil {
27-
return nil, fmt.Errorf("failed to create workload manager: %w", err)
28-
}
29-
30-
return &manager{store: store, workloadManager: workloadManager}, nil
31-
}
32-
33-
// NewManagerWithWorkloadManager creates a new group manager with a custom workload manager
34-
// This is useful for testing with mocks
35-
func NewManagerWithWorkloadManager(workloadManager workloads.Manager) (Manager, error) {
36-
store, err := state.NewGroupConfigStore("toolhive")
37-
if err != nil {
38-
return nil, fmt.Errorf("failed to create group state store: %w", err)
39-
}
40-
41-
return &manager{store: store, workloadManager: workloadManager}, nil
25+
return &manager{store: store}, nil
4226
}
4327

4428
// Create creates a new group with the given name
@@ -108,22 +92,21 @@ func (m *manager) Exists(ctx context.Context, name string) (bool, error) {
10892

10993
// GetWorkloadGroup returns the group that a workload belongs to, if any
11094
func (m *manager) GetWorkloadGroup(ctx context.Context, workloadName string) (*Group, error) {
111-
// Use the workload manager to get the workload and check its group label
112-
113-
// Get the workload details
114-
workload, err := m.workloadManager.GetWorkload(ctx, workloadName)
95+
runnerInstance, err := runner.LoadState(ctx, workloadName)
11596
if err != nil {
116-
// If workload not found, it's not in any group
117-
return nil, nil
97+
if errors.IsRunConfigNotFound(err) {
98+
return nil, nil
99+
}
100+
return nil, err
118101
}
119102

120-
// Check if the workload has a group
121-
if workload.Group == "" {
122-
return nil, nil // Workload is not in any group
103+
// If the workload has no group, return nil
104+
if runnerInstance.Config.Group == "" {
105+
return nil, nil
123106
}
124107

125108
// Get the group details
126-
return m.Get(ctx, workload.Group)
109+
return m.Get(ctx, runnerInstance.Config.Group)
127110
}
128111

129112
// saveGroup saves the group to the group state store

pkg/labels/labels.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@ const (
4040
LabelToolHiveValue = "true"
4141
)
4242

43-
// AddStandardLabelsWithGroup adds standard labels to a container, including group if provided
44-
func AddStandardLabelsWithGroup(labels map[string]string, containerName, containerBaseName, transportType string,
45-
port int, groupName string) {
43+
// AddStandardLabels adds standard labels to a container
44+
func AddStandardLabels(labels map[string]string, containerName, containerBaseName, transportType string, port int) {
4645
labels[LabelToolHive] = LabelToolHiveValue
4746
labels[LabelName] = containerName
4847
labels[LabelBaseName] = containerBaseName
@@ -51,14 +50,6 @@ func AddStandardLabelsWithGroup(labels map[string]string, containerName, contain
5150

5251
// TODO: In the future, we'll support different tool types beyond just "mcp"
5352
labels[LabelToolType] = "mcp"
54-
if groupName != "" {
55-
labels[LabelGroup] = groupName
56-
}
57-
}
58-
59-
// AddStandardLabels adds standard labels to a container
60-
func AddStandardLabels(labels map[string]string, containerName, containerBaseName, transportType string, port int) {
61-
AddStandardLabelsWithGroup(labels, containerName, containerBaseName, transportType, port, "")
6253
}
6354

6455
// AddNetworkLabels adds network-related labels to a network
@@ -148,7 +139,6 @@ func IsStandardToolHiveLabel(key string) bool {
148139
LabelPort,
149140
LabelToolType,
150141
LabelNetworkIsolation,
151-
LabelGroup,
152142
}
153143

154144
for _, standardLabel := range standardLabels {

0 commit comments

Comments
 (0)