diff --git a/apis/servmanager.go b/apis/servmanager.go index 85accfae1..a13a4253a 100644 --- a/apis/servmanager.go +++ b/apis/servmanager.go @@ -32,14 +32,14 @@ type ServiceManagerV1 struct { ping } -func (servManager *ServiceManagerV1) StartService(ctx *context.Context, args *servmanager.ArgsServiceID, reply *string) (err error) { +func (servManager *ServiceManagerV1) StartService(ctx *context.Context, args *servmanager.ArgsServiceID, reply *string) error { return servManager.sm.V1StartService(ctx, args, reply) } -func (servManager *ServiceManagerV1) StopService(ctx *context.Context, args *servmanager.ArgsServiceID, reply *string) (err error) { +func (servManager *ServiceManagerV1) StopService(ctx *context.Context, args *servmanager.ArgsServiceID, reply *string) error { return servManager.sm.V1StopService(ctx, args, reply) } -func (servManager *ServiceManagerV1) ServiceStatus(ctx *context.Context, args *servmanager.ArgsServiceID, reply *string) (err error) { +func (servManager *ServiceManagerV1) ServiceStatus(ctx *context.Context, args *servmanager.ArgsServiceID, reply *map[string]string) error { return servManager.sm.V1ServiceStatus(ctx, args, reply) } diff --git a/apis/servmanager_it_test.go b/apis/servmanager_it_test.go index 25dc7e32c..bf09296a4 100644 --- a/apis/servmanager_it_test.go +++ b/apis/servmanager_it_test.go @@ -144,15 +144,16 @@ func testSrvMngPing(t *testing.T) { Run the following tests for each service: - ping before enabling service (expect can't find service error) - - query for service status (expect "STOPPED" reply) + - query for service status (expect service to be in state "SERVICE_DOWN") - start the service - - query for service status (expect "RUNNING" reply) + - query for service status (expect service to be in state "SERVICE_UP") - ping (expect "Pong") - stop service - - query for service status (expect "STOPPED" reply) + - query for service status (expect service to be in state "SERVICE_DOWN" reply) - ping after stopping service (expect "can't find service" error) */ + var statusReply map[string]string for serviceID, serviceMethod := range serviceToMethod { t.Run(fmt.Sprintf("test for service %s", serviceID), func(t *testing.T) { rpcErr := fmt.Sprintf("rpc: can't find service %s", serviceMethod) @@ -166,10 +167,10 @@ func testSrvMngPing(t *testing.T) { } if err := srvMngRPC.Call(context.Background(), utils.ServiceManagerV1ServiceStatus, args, - &reply); err != nil { + &statusReply); err != nil { t.Error(err) - } else if reply != utils.StoppedCaps { - t.Errorf("Unexpected reply: %s", reply) + } else if statusReply[serviceID] != utils.StateServiceDOWN { + t.Errorf("Unexpected reply: %s", utils.ToJSON(statusReply)) } if err := srvMngRPC.Call(context.Background(), utils.ServiceManagerV1StartService, args, @@ -180,10 +181,10 @@ func testSrvMngPing(t *testing.T) { } if err := srvMngRPC.Call(context.Background(), utils.ServiceManagerV1ServiceStatus, args, - &reply); err != nil { + &statusReply); err != nil { t.Error(err) - } else if reply != utils.RunningCaps { - t.Errorf("Unexpected reply: %s", reply) + } else if statusReply[serviceID] != utils.StateServiceUP { + t.Errorf("Unexpected reply: %s", utils.ToJSON(statusReply)) } if err := srvMngRPC.Call(context.Background(), serviceMethod, nil, @@ -201,10 +202,10 @@ func testSrvMngPing(t *testing.T) { } if err := srvMngRPC.Call(context.Background(), utils.ServiceManagerV1ServiceStatus, args, - &reply); err != nil { + &statusReply); err != nil { t.Error(err) - } else if reply != utils.StoppedCaps { - t.Errorf("Unexpected reply: %s", reply) + } else if statusReply[serviceID] != utils.StateServiceDOWN { + t.Errorf("Unexpected reply: %s", utils.ToJSON(statusReply)) } if err := srvMngRPC.Call(context.Background(), serviceMethod, nil, diff --git a/servmanager/servmanager.go b/servmanager/servmanager.go index b35ffb586..3725bf81e 100644 --- a/servmanager/servmanager.go +++ b/servmanager/servmanager.go @@ -21,6 +21,7 @@ package servmanager import ( "fmt" "slices" + "strings" "sync" "github.com/cgrates/birpc/context" @@ -183,21 +184,27 @@ func (m *ServiceManager) V1StopService(ctx *context.Context, args *ArgsServiceID return } -// V1ServiceStatus returns the service status -func (m *ServiceManager) V1ServiceStatus(ctx *context.Context, args *ArgsServiceID, reply *string) error { +// V1ServiceStatus returns the current state of the specified services. +func (m *ServiceManager) V1ServiceStatus(ctx *context.Context, args *ArgsServiceID, reply *map[string]string) error { m.RLock() defer m.RUnlock() - - svc := m.registry.Lookup(args.ServiceID) - if svc == nil { - return utils.ErrUnsupportedServiceID - } - - if IsServiceInState(svc, utils.StateServiceUP) { - *reply = utils.RunningCaps - } else { - *reply = utils.StoppedCaps + states := make(map[string]string) + switch args.ServiceID { + case utils.MetaAll: + for _, svc := range m.registry.List() { + states[svc.ServiceName()] = State(svc) + } + default: + ids := strings.Split(args.ServiceID, utils.FieldsSep) + for _, id := range ids { + svc := m.registry.Lookup(id) + if svc == nil { + return fmt.Errorf("unsupported service ID: %q", id) + } + states[id] = State(svc) + } } + *reply = states return nil } @@ -299,16 +306,6 @@ func toggleService(id string, status bool, srvMngr *ServiceManager) (err error) return } -// IsServiceInState performs a non-blocking check to determine if a service is in the specified state. -func IsServiceInState(svc Service, state string) bool { - select { - case <-svc.StateChan(state): - return true - default: - return false - } -} - // MustSetState changes a service's state, panicking if it fails. func MustSetState(svc Service, state string) { if err := SetState(svc, state); err != nil {