Added *remote_set_account action

This commit is contained in:
Trial97
2020-11-20 17:14:16 +02:00
committed by Dan Christian Bogos
parent 3c06f49246
commit ffaac358d5
6 changed files with 169 additions and 5 deletions

View File

@@ -106,6 +106,7 @@ func getActionFunc(typ string) (actionTypeFunc, bool) {
utils.MetaExport: export,
utils.MetaResetThreshold: resetThreshold,
utils.MetaResetStatQueue: resetStatQueue,
utils.MetaRemoteSetAccount: remoteSetAccount,
}
f, exists := actionFuncMap[typ]
return f, exists
@@ -1069,3 +1070,24 @@ func resetStatQueue(ub *Account, a *Action, acs Actions, extraData interface{})
return connMgr.Call(config.CgrConfig().SchedulerCfg().StatSConns, nil,
utils.StatSv1ResetStatQueue, args, &rply)
}
func remoteSetAccount(ub *Account, a *Action, acs Actions, extraData interface{}) (err error) {
client := &http.Client{Transport: httpPstrTransport}
var resp *http.Response
req := new(bytes.Buffer)
if err = json.NewEncoder(req).Encode(ub); err != nil {
return
}
if resp, err = client.Post(a.ExtraParameters, "application/json", req); err != nil {
return
}
acc := new(Account)
err = json.NewDecoder(resp.Body).Decode(acc)
if err != nil {
return
}
if len(acc.BalanceMap) != 0 {
*ub = *acc
}
return
}

View File

@@ -204,9 +204,15 @@ func (at *ActionTiming) Execute(successActions, failedActions chan *Action) (err
for accID := range at.accountIDs {
_, err = guardian.Guardian.Guard(func() (interface{}, error) {
acc, err := dm.GetAccount(accID)
if err != nil {
utils.Logger.Warning(fmt.Sprintf("Could not get account id: %s. Skipping!", accID))
return 0, err
if err != nil { // create account
if err != utils.ErrNotFound {
utils.Logger.Warning(fmt.Sprintf("Could not get account id: %s. Skipping!", accID))
return 0, err
}
err = nil
acc = &Account{
ID: accID,
}
}
transactionFailed := false
removeAccountActionFound := false

View File

@@ -19,6 +19,9 @@ package engine
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
@@ -2625,13 +2628,13 @@ func TestCdrLogAction(t *testing.T) {
acc := &Account{
ID: "cgrates.org:1001",
BalanceMap: map[string]Balances{
utils.MONETARY: Balances{
utils.MONETARY: {
&Balance{Value: 20},
},
},
UnitCounters: UnitCounters{
utils.MONETARY: []*UnitCounter{
&UnitCounter{
{
Counters: CounterFilters{
&CounterFilter{Value: 1},
},
@@ -2701,6 +2704,71 @@ func TestCdrLogAction(t *testing.T) {
}
}
func TestRemoteSetAccountAction(t *testing.T) {
expError := `Post "127.1.0.11//": unsupported protocol scheme ""`
if err = remoteSetAccount(nil, &Action{ExtraParameters: "127.1.0.11//"}, nil, nil); err == nil ||
err.Error() != expError {
t.Fatalf("Expected error: %s, received: %v", expError, err)
}
expError = `json: unsupported type: func()`
if err = remoteSetAccount(&Account{
ActionTriggers: ActionTriggers{{
Balance: &BalanceFilter{
Value: &utils.ValueFormula{
Params: map[string]interface{}{utils.VOICE: func() {}},
},
},
}},
}, &Action{ExtraParameters: "127.1.0.11//"}, nil, nil); err == nil ||
err.Error() != expError {
t.Fatalf("Expected error: %s, received: %v", expError, err)
}
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { rw.Write([]byte("5")) }))
acc := &Account{ID: "1001"}
expError = `json: cannot unmarshal number into Go value of type engine.Account`
if err = remoteSetAccount(acc, &Action{ExtraParameters: ts.URL}, nil, nil); err == nil ||
err.Error() != expError {
t.Fatalf("Expected error: %s, received: %v", expError, err)
}
exp := &Account{ID: "1001"}
if !reflect.DeepEqual(exp, acc) {
t.Errorf("Expected: %s,received: %s", utils.ToJSON(exp), utils.ToJSON(acc))
}
ts.Close()
acc = &Account{ID: "1001"}
exp = &Account{
ID: "1001",
BalanceMap: map[string]Balances{
utils.META_VOICE: {{
ID: "money",
Value: 15,
}},
},
}
ts = httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
accStr := utils.ToJSON(acc) + "\n"
val, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
t.Error(err)
return
}
if string(val) != accStr {
t.Errorf("Expected %q,received: %q", accStr, string(val))
return
}
rw.Write([]byte(utils.ToJSON(exp)))
}))
if err = remoteSetAccount(acc, &Action{ExtraParameters: ts.URL}, nil, nil); err != nil {
t.Fatal(err)
} else if !reflect.DeepEqual(exp, acc) {
t.Errorf("Expected: %s,received: %s", utils.ToJSON(exp), utils.ToJSON(acc))
}
ts.Close()
}
/**************** Benchmarks ********************************/
func BenchmarkUUID(b *testing.B) {

View File

@@ -20,6 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package engine
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"net/rpc"
"path"
"reflect"
@@ -53,6 +56,7 @@ var (
testActionsitThresholdPostEvent,
testActionsitSetSDestinations,
testActionsitresetAccountCDR,
testActionsitremoteSetAccount,
testActionsitStopCgrEngine,
}
)
@@ -925,3 +929,65 @@ func testActionsitStopCgrEngine(t *testing.T) {
t.Error(err)
}
}
func testActionsitremoteSetAccount(t *testing.T) {
var reply string
account := "remote1234"
accID := utils.ConcatenatedKey("cgrates.org", account)
acc := &Account{
ID: accID,
}
exp := &Account{
ID: accID,
BalanceMap: map[string]Balances{
utils.MONETARY: []*Balance{{
Value: 20,
Weight: 10,
}},
},
}
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
accStr := utils.ToJSON(acc) + "\n"
val, err := ioutil.ReadAll(r.Body)
r.Body.Close()
if err != nil {
t.Error(err)
return
}
if string(val) != accStr {
t.Errorf("Expected %q,received: %q", accStr, string(val))
return
}
rw.Write([]byte(utils.ToJSON(exp)))
}))
defer ts.Close()
attrsAA := &utils.AttrSetActions{
ActionsId: "remoteSetAccountCDR",
Actions: []*utils.TPAction{
{Identifier: utils.MetaRemoteSetAccount, ExtraParameters: ts.URL, Weight: 20.0},
},
}
if err := actsLclRpc.Call(utils.APIerSv2SetActions, attrsAA, &reply); err != nil && err.Error() != utils.ErrExists.Error() {
t.Error("Got error on APIerSv2.SetActions: ", err.Error())
} else if reply != utils.OK {
t.Errorf("Calling APIerSv2.SetActions received: %s", reply)
}
attrsEA := &utils.AttrExecuteAction{Tenant: "cgrates.org", Account: account, ActionsId: attrsAA.ActionsId}
if err := actsLclRpc.Call(utils.APIerSv1ExecuteAction, attrsEA, &reply); err != nil {
t.Error("Got error on APIerSv1.ExecuteAction: ", err.Error())
} else if reply != utils.OK {
t.Errorf("Calling APIerSv1.ExecuteAction received: %s", reply)
}
var acc2 Account
attrs2 := &utils.AttrGetAccount{Account: account}
if err := actsLclRpc.Call(utils.APIerSv2GetAccount, attrs2, &acc2); err != nil {
t.Fatal("Got error on APIerSv1.GetAccount: ", err.Error())
}
acc2.UpdateTime = exp.UpdateTime
if utils.ToJSON(exp) != utils.ToJSON(acc2) {
t.Errorf("Expected: %s,received: %s", utils.ToJSON(exp), utils.ToJSON(acc2))
}
}

View File

@@ -132,6 +132,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium
* [RouteS] Add new field RouteRateProfileIDs in RateProfiles.csv
* [DispatcherS] Removed connection pool from DispatcherHost structure
* [DispatcherS] Updated *broadcast, *broadcast_sync and *broadcast_async to behave similar to RPCPool
* [ActionsS] Added *remote_set_account action
-- DanB <danb@cgrates.org> Wed, 19 Feb 2020 13:25:52 +0200

View File

@@ -1002,6 +1002,7 @@ const (
MetaCDRAccount = "*reset_account_cdr"
MetaResetThreshold = "*reset_threshold"
MetaResetStatQueue = "*reset_stat_queue"
MetaRemoteSetAccount = "*remote_set_account"
ActionID = "ActionID"
ActionType = "ActionType"
ActionValue = "ActionValue"