1
1
package app
2
2
3
3
import (
4
+ "context"
4
5
"errors"
5
6
"fmt"
6
7
7
8
"github.com/spf13/cobra"
8
9
"golang.org/x/sync/errgroup"
9
10
10
11
rt "github.com/stacklok/toolhive/pkg/container/runtime"
12
+ "github.com/stacklok/toolhive/pkg/groups"
11
13
"github.com/stacklok/toolhive/pkg/workloads"
12
14
"github.com/stacklok/toolhive/pkg/workloads/types"
13
15
)
@@ -24,25 +26,34 @@ var stopCmd = &cobra.Command{
24
26
var (
25
27
stopTimeout int
26
28
stopAll bool
29
+ stopGroup string
27
30
)
28
31
29
32
func init () {
30
33
stopCmd .Flags ().IntVar (& stopTimeout , "timeout" , 30 , "Timeout in seconds before forcibly stopping the workload" )
31
34
stopCmd .Flags ().BoolVar (& stopAll , "all" , false , "Stop all running MCP servers" )
35
+ // TODO: Re-enable group flag when groups are implemented
36
+ //stopCmd.Flags().StringVarP(&stopGroup, "group", "g", "", "Stop all MCP servers in a specific group")
37
+ //
38
+ //// Mark the flags as mutually exclusive
39
+ //stopCmd.MarkFlagsMutuallyExclusive("all", "group")
40
+ //
41
+ //stopCmd.PreRunE = validateGroupFlag()
32
42
}
33
43
34
44
// validateStopArgs validates the arguments for the stop command
35
45
func validateStopArgs (cmd * cobra.Command , args []string ) error {
36
- // Check if --all flag is set
46
+ // Check if --all or --group flags are set
37
47
all , _ := cmd .Flags ().GetBool ("all" )
48
+ group , _ := cmd .Flags ().GetString ("group" )
38
49
39
- if all {
40
- // If --all is set, no arguments should be provided
50
+ if all || group != "" {
51
+ // If --all or --group is set, no arguments should be provided
41
52
if len (args ) > 0 {
42
- return fmt .Errorf ("no arguments should be provided when --all flag is set" )
53
+ return fmt .Errorf ("no arguments should be provided when --all or --group flag is set" )
43
54
}
44
55
} else {
45
- // If --all is not set, exactly one argument should be provided
56
+ // If neither --all nor --group is set, exactly one argument should be provided
46
57
if len (args ) != 1 {
47
58
return fmt .Errorf ("exactly one workload name must be provided" )
48
59
}
@@ -61,59 +72,119 @@ func stopCmdFunc(cmd *cobra.Command, args []string) error {
61
72
62
73
var group * errgroup.Group
63
74
64
- // Check if --all flag is set
65
75
if stopAll {
66
- // Get list of all running workloads first
67
- workloadList , err := workloadManager .ListWorkloads (ctx , false ) // false = only running workloads
68
- if err != nil {
69
- return fmt .Errorf ("failed to list workloads: %v" , err )
70
- }
76
+ return stopAllWorkloads (ctx , workloadManager )
77
+ }
71
78
72
- // Extract workload names
73
- var workloadNames []string
74
- for _ , workload := range workloadList {
75
- workloadNames = append (workloadNames , workload .Name )
76
- }
79
+ if stopGroup != "" {
80
+ return stopWorkloadsByGroup (ctx , workloadManager , stopGroup )
81
+ }
77
82
78
- if len (workloadNames ) == 0 {
79
- fmt .Println ("No running workloads to stop" )
83
+ // Stop single workload
84
+ workloadName := args [0 ]
85
+ group , err = workloadManager .StopWorkloads (ctx , []string {workloadName })
86
+ if err != nil {
87
+ // If the workload is not found or not running, treat as a non-fatal error.
88
+ if errors .Is (err , rt .ErrWorkloadNotFound ) ||
89
+ errors .Is (err , workloads .ErrWorkloadNotRunning ) ||
90
+ errors .Is (err , types .ErrInvalidWorkloadName ) {
91
+ fmt .Printf ("workload %s is not running\n " , workloadName )
80
92
return nil
81
93
}
94
+ return fmt .Errorf ("unexpected error stopping workload: %v" , err )
95
+ }
82
96
83
- // Stop all workloads using the bulk method
84
- group , err = workloadManager . StopWorkloads ( ctx , workloadNames )
85
- if err != nil {
86
- return fmt . Errorf ( "failed to stop all workloads: %v" , err )
87
- }
97
+ // Since the stop operation is asynchronous, wait for the group to finish.
98
+ if err := group . Wait (); err != nil {
99
+ return fmt . Errorf ( "failed to stop workload %s: %v" , workloadName , err )
100
+ }
101
+ fmt . Printf ( "workload %s stopped successfully \n " , workloadName )
88
102
89
- // Since the stop operation is asynchronous, wait for the group to finish.
90
- if err := group .Wait (); err != nil {
91
- return fmt .Errorf ("failed to stop all workloads: %v" , err )
92
- }
93
- fmt .Println ("All workloads stopped successfully" )
94
- } else {
95
- // Get workload name
96
- workloadName := args [0 ]
97
-
98
- // Stop a single workload
99
- group , err = workloadManager .StopWorkloads (ctx , []string {workloadName })
100
- if err != nil {
101
- // If the workload is not found or not running, treat as a non-fatal error.
102
- if errors .Is (err , rt .ErrWorkloadNotFound ) ||
103
- errors .Is (err , workloads .ErrWorkloadNotRunning ) ||
104
- errors .Is (err , types .ErrInvalidWorkloadName ) {
105
- fmt .Printf ("workload %s is not running\n " , workloadName )
106
- return nil
107
- }
108
- return fmt .Errorf ("unexpected error stopping workload: %v" , err )
109
- }
103
+ return nil
104
+ }
110
105
111
- // Since the stop operation is asynchronous, wait for the group to finish.
112
- if err := group .Wait (); err != nil {
113
- return fmt .Errorf ("failed to stop workload %s: %v" , workloadName , err )
114
- }
115
- fmt .Printf ("workload %s stopped successfully\n " , workloadName )
106
+ func stopAllWorkloads (ctx context.Context , workloadManager workloads.Manager ) error {
107
+ // Get list of all running workloads first
108
+ workloadList , err := workloadManager .ListWorkloads (ctx , false ) // false = only running workloads
109
+ if err != nil {
110
+ return fmt .Errorf ("failed to list workloads: %v" , err )
111
+ }
112
+
113
+ // Extract workload names
114
+ var workloadNames []string
115
+ for _ , workload := range workloadList {
116
+ workloadNames = append (workloadNames , workload .Name )
117
+ }
118
+
119
+ if len (workloadNames ) == 0 {
120
+ fmt .Println ("No running workloads to stop" )
121
+ return nil
122
+ }
123
+
124
+ // Stop all workloads using the bulk method
125
+ group , err := workloadManager .StopWorkloads (ctx , workloadNames )
126
+ if err != nil {
127
+ return fmt .Errorf ("failed to stop all workloads: %v" , err )
128
+ }
129
+
130
+ // Since the stop operation is asynchronous, wait for the group to finish.
131
+ if err := group .Wait (); err != nil {
132
+ return fmt .Errorf ("failed to stop all workloads: %v" , err )
133
+ }
134
+ fmt .Println ("All workloads stopped successfully" )
135
+ return nil
136
+ }
137
+
138
+ func stopWorkloadsByGroup (ctx context.Context , workloadManager workloads.Manager , groupName string ) error {
139
+ // Create a groups manager to list workloads in the group
140
+ groupManager , err := groups .NewManager ()
141
+ if err != nil {
142
+ return fmt .Errorf ("failed to create group manager: %v" , err )
143
+ }
144
+
145
+ // Check if the group exists
146
+ exists , err := groupManager .Exists (ctx , groupName )
147
+ if err != nil {
148
+ return fmt .Errorf ("failed to check if group '%s' exists: %v" , groupName , err )
149
+ }
150
+ if ! exists {
151
+ return fmt .Errorf ("group '%s' does not exist" , groupName )
152
+ }
153
+
154
+ // Get list of running workloads and filter by group
155
+ workloadList , err := workloadManager .ListWorkloads (ctx , false ) // false = only running workloads
156
+ if err != nil {
157
+ return fmt .Errorf ("failed to list running workloads: %v" , err )
158
+ }
159
+
160
+ // Filter workloads by group
161
+ groupWorkloads , err := workloads .FilterByGroup (workloadList , groupName )
162
+ if err != nil {
163
+ return fmt .Errorf ("failed to filter workloads by group: %v" , err )
164
+ }
165
+
166
+ if len (groupWorkloads ) == 0 {
167
+ fmt .Printf ("No running MCP servers found in group '%s'\n " , groupName )
168
+ return nil
169
+ }
170
+
171
+ // Extract workload names from the filtered list
172
+ var workloadNames []string
173
+ for _ , workload := range groupWorkloads {
174
+ workloadNames = append (workloadNames , workload .Name )
175
+ }
176
+
177
+ // Stop workloads in the group
178
+ subtasks , err := workloadManager .StopWorkloads (ctx , workloadNames )
179
+ if err != nil {
180
+ return fmt .Errorf ("failed to stop workloads in group '%s': %v" , groupName , err )
181
+ }
182
+
183
+ // Wait for the stop operation to complete
184
+ if err := subtasks .Wait (); err != nil {
185
+ return fmt .Errorf ("failed to stop workloads in group '%s': %v" , groupName , err )
116
186
}
117
187
188
+ fmt .Printf ("Successfully stopped %d workload(s) in group '%s'\n " , len (workloadNames ), groupName )
118
189
return nil
119
190
}
0 commit comments