From 4ba102b3d476615022571ed14e8be7c552999a9c Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 27 Feb 2019 16:09:47 +0200 Subject: [PATCH] Added Responder.Status for DispatcheSv1 and tests for *random strategy --- apier/v1/dispatcher.go | 13 ++ cmd/cgr-engine/cgr-engine.go | 3 + console/status.go | 4 +- data/tariffplans/dispatchers/Attributes.csv | 1 + data/tariffplans/dispatchers/Dispatchers.csv | 2 + dispatchers/responder.go | 39 ++++++ dispatchers/responder_it_test.go | 118 +++++++++++++++++++ 7 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 dispatchers/responder.go create mode 100644 dispatchers/responder_it_test.go diff --git a/apier/v1/dispatcher.go b/apier/v1/dispatcher.go index 3bf98f472..a8efd64ac 100755 --- a/apier/v1/dispatcher.go +++ b/apier/v1/dispatcher.go @@ -362,3 +362,16 @@ func (dS *DispatcherSessionSv1) SetPassiveSession(args *dispatchers.SessionWithA reply *string) (err error) { return dS.dS.SessionSv1SetPassiveSession(args, reply) } + +func NewDispatcherResponder(dps *dispatchers.DispatcherService) *DispatcherResponder { + return &DispatcherResponder{dS: dps} +} + +// Exports RPC from RLs +type DispatcherResponder struct { + dS *dispatchers.DispatcherService +} + +func (dS *DispatcherResponder) Status(args *dispatchers.TntWithApiKey, reply *map[string]interface{}) error { + return dS.dS.ResponderStatus(args, reply) +} diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 16053cd38..c1a58d7aa 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -981,6 +981,9 @@ func startDispatcherService(internalDispatcherSChan chan *dispatchers.Dispatcher server.RpcRegisterName(utils.ChargerSv1, v1.NewDispatcherChargerSv1(dspS)) + server.RpcRegisterName(utils.Responder, + v1.NewDispatcherResponder(dspS)) + internalDispatcherSChan <- dspS } diff --git a/console/status.go b/console/status.go index c70b9ef8d..e01d04c77 100644 --- a/console/status.go +++ b/console/status.go @@ -18,10 +18,12 @@ along with this program. If not, see package console +import "github.com/cgrates/cgrates/utils" + func init() { c := &CmdStatus{ name: "status", - rpcMethod: "Responder.Status", + rpcMethod: utils.ResponderStatus, } commands[c.Name()] = c c.CommandExecuter = &CommandExecuter{c} diff --git a/data/tariffplans/dispatchers/Attributes.csv b/data/tariffplans/dispatchers/Attributes.csv index 2ca0f2544..c0aa84ab8 100644 --- a/data/tariffplans/dispatchers/Attributes.csv +++ b/data/tariffplans/dispatchers/Attributes.csv @@ -8,4 +8,5 @@ cgrates.org,ATTR_API_SUP_AUTH,*auth,*string:APIKey:sup12345,,APIMethods,*any,Sup cgrates.org,ATTR_API_STAT_AUTH,*auth,*string:APIKey:stat12345,,APIMethods,*any,StatSv1.Ping&StatSv1.GetStatQueuesForEvent&StatSv1.GetQueueStringMetrics&StatSv1.ProcessEvent&StatSv1.GetQueueIDs&StatSv1.GetQueueFloatMetrics,true,false,20 cgrates.org,ATTR_API_RES_AUTH,*auth,*string:APIKey:res12345,,APIMethods,*any,ResourceSv1.Ping&ResourceSv1.GetResourcesForEvent&ResourceSv1.AuthorizeResources&ResourceSv1.AllocateResources&ResourceSv1.ReleaseResources,true,false,20 cgrates.org,ATTR_API_SES_AUTH,*auth,*string:APIKey:ses12345,,APIMethods,*any,SessionSv1.Ping&SessionSv1.AuthorizeEventWithDigest&SessionSv1.InitiateSessionWithDigest&SessionSv1.UpdateSession&SessionSv1.TerminateSession&SessionSv1.ProcessCDR&SessionSv1.ProcessEvent&SessionSv1.GetActiveSessions&SessionSv1.GetActiveSessionsCount&SessionSv1.ForceDisconnect&SessionSv1.GetPassiveSessions&SessionSv1.GetPassiveSessionsCount&SessionSv1.SetPassiveSession&SessionSv1.ReplicateSessions,true,false,20 +cgrates.org,ATTR_API_RSP_AUTH,*auth,*string:APIKey:rsp12345,,APIMethods,*any,Responder.Status,true,false,20 diff --git a/data/tariffplans/dispatchers/Dispatchers.csv b/data/tariffplans/dispatchers/Dispatchers.csv index c9b788c87..ae6a8f6e8 100644 --- a/data/tariffplans/dispatchers/Dispatchers.csv +++ b/data/tariffplans/dispatchers/Dispatchers.csv @@ -5,3 +5,5 @@ cgrates.org,EVENT1,*any,*string:EventName:Event1,,*weight,,ALL2,,20,false,,30 cgrates.org,EVENT1,,,,,,ALL,,10,,, cgrates.org,EVENT2,*any,*string:EventName:RoundRobin,,*round_robin,,ALL2,,20,false,,20 cgrates.org,EVENT2,,,,,,ALL,,10,,, +cgrates.org,EVENT3,*any,*string:EventName:Random,,*random,,ALL2,,20,false,,20 +cgrates.org,EVENT3,,,,,,ALL,,10,,, diff --git a/dispatchers/responder.go b/dispatchers/responder.go new file mode 100644 index 000000000..a19fdd60e --- /dev/null +++ b/dispatchers/responder.go @@ -0,0 +1,39 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package dispatchers + +import ( + "time" + + "github.com/cgrates/cgrates/utils" +) + +func (dS *DispatcherService) ResponderStatus(args *TntWithApiKey, + reply *map[string]interface{}) (err error) { + if dS.attrS != nil { + if err = dS.authorize(utils.ResponderStatus, args.Tenant, + args.APIKey, utils.TimePointer(time.Now())); err != nil { + return + } + } + return dS.Dispatch(&utils.CGREvent{ + Tenant: args.Tenant, + }, utils.MetaStats, args.RouteID, utils.ResponderStatus, + "", reply) +} diff --git a/dispatchers/responder_it_test.go b/dispatchers/responder_it_test.go new file mode 100644 index 000000000..ee90119fe --- /dev/null +++ b/dispatchers/responder_it_test.go @@ -0,0 +1,118 @@ +// +build integration + +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package dispatchers + +import ( + "fmt" + "testing" + + "github.com/cgrates/cgrates/utils" +) + +var sTestsDspRsp = []func(t *testing.T){ + testDspResponderStatus, + + testDspResponderRandom, +} + +//Test start here +func TestDspResponderTMySQL(t *testing.T) { + testDsp(t, sTestsDspRsp, "TestDspAttributeS", "all", "all2", "attributes", "dispatchers", "tutorial", "oldtutorial", "dispatchers") +} + +func TestDspResponderMongo(t *testing.T) { + testDsp(t, sTestsDspRsp, "TestDspAttributeS", "all", "all2", "attributes_mongo", "dispatchers_mongo", "tutorial", "oldtutorial", "dispatchers") +} + +func testDspResponderStatus(t *testing.T) { + var reply map[string]interface{} + if err := allEngine.RCP.Call(utils.ResponderStatus, "", &reply); err != nil { + t.Error(err) + } else if reply[utils.NodeID] != "ALL" { + t.Errorf("Received: %s", reply) + } + ev := TntWithApiKey{ + TenantArg: utils.TenantArg{ + Tenant: "cgrates.org", + }, + DispatcherResource: DispatcherResource{ + APIKey: "rsp12345", + }, + } + if err := dispEngine.RCP.Call(utils.ResponderStatus, &ev, &reply); err != nil { + t.Error(err) + } else if reply[utils.NodeID] != "ALL" { + t.Errorf("Received: %s", utils.ToJSON(reply)) + } + allEngine.stopEngine(t) + if err := dispEngine.RCP.Call(utils.ResponderStatus, &ev, &reply); err != nil { + t.Error(err) + } else if reply[utils.NodeID] != "ALL2" { + t.Errorf("Received: %s", utils.ToJSON(reply)) + } + allEngine.startEngine(t) +} + +func getNodeWithRoute(route string, t *testing.T) string { + var reply map[string]interface{} + var pingReply string + pingEv := CGREvWithApiKey{ + CGREvent: utils.CGREvent{ + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.EVENT_NAME: "Random", + }, + }, + DispatcherResource: DispatcherResource{ + APIKey: "attr12345", + RouteID: &route, + }, + } + ev := TntWithApiKey{ + TenantArg: utils.TenantArg{ + Tenant: "cgrates.org", + }, + DispatcherResource: DispatcherResource{ + APIKey: "rsp12345", + RouteID: &route, + }, + } + + if err := dispEngine.RCP.Call(utils.AttributeSv1Ping, pingEv, &pingReply); err != nil { + t.Error(err) + } else if pingReply != utils.Pong { + t.Errorf("Received: %s", pingReply) + } + if err := dispEngine.RCP.Call(utils.ResponderStatus, &ev, &reply); err != nil { + t.Error(err) + } + return reply[utils.NodeID].(string) +} + +func testDspResponderRandom(t *testing.T) { + node := getNodeWithRoute("r_init", t) + for i := 0; i < 10; i++ { + if node != getNodeWithRoute(fmt.Sprintf("R_%v", i), t) { + return + } + } + t.Errorf("Random strategy fail with 0.0009765625%% probability") +}