diff --git a/apier/v1/tp.go b/apier/v1/tp.go index b08459f6b..42291c5ff 100644 --- a/apier/v1/tp.go +++ b/apier/v1/tp.go @@ -21,6 +21,7 @@ package v1 // Tariff plan related APIs import ( + "encoding/base64" "io/ioutil" "os" "path/filepath" @@ -97,3 +98,76 @@ func (self *ApierV1) ImportTPZipFile(attrs AttrImportTPZipFile, reply *string) e *reply = utils.OK return nil } + +type AttrRemTp struct { + TPid string +} + +func (self *ApierV1) RemTP(attrs AttrRemTp, reply *string) error { + if len(attrs.TPid) == 0 { + return utils.NewErrMandatoryIeMissing("TPid") + } + if err := self.StorDb.RemTpData("", attrs.TPid, nil); err != nil { + return utils.NewErrServerError(err) + } else { + *reply = utils.OK + } + return nil +} + +func (self *ApierV1) ExportTPToFolder(attrs utils.AttrDirExportTP, exported *utils.ExportedTPStats) error { + if attrs.TPid == nil || *attrs.TPid == "" { + return utils.NewErrMandatoryIeMissing("TPid") + } + dir := self.Config.TpExportPath + if attrs.ExportPath != nil { + dir = *attrs.ExportPath + } + fileFormat := utils.CSV + if attrs.FileFormat != nil { + fileFormat = *attrs.FileFormat + } + sep := "," + if attrs.FieldSeparator != nil { + sep = *attrs.FieldSeparator + } + compress := false + if attrs.Compress != nil { + compress = *attrs.Compress + } + tpExporter, err := engine.NewTPExporter(self.StorDb, *attrs.TPid, dir, fileFormat, sep, compress) + if err != nil { + return utils.NewErrServerError(err) + } + if err := tpExporter.Run(); err != nil { + return utils.NewErrServerError(err) + } else { + *exported = *tpExporter.ExportStats() + } + + return nil +} + +func (self *ApierV1) ExportTPToZipString(attrs utils.AttrDirExportTP, reply *string) error { + if attrs.TPid == nil || *attrs.TPid == "" { + return utils.NewErrMandatoryIeMissing("TPid") + } + dir := "" + fileFormat := utils.CSV + if attrs.FileFormat != nil { + fileFormat = *attrs.FileFormat + } + sep := "," + if attrs.FieldSeparator != nil { + sep = *attrs.FieldSeparator + } + tpExporter, err := engine.NewTPExporter(self.StorDb, *attrs.TPid, dir, fileFormat, sep, true) + if err != nil { + return utils.NewErrServerError(err) + } + if err := tpExporter.Run(); err != nil { + return utils.NewErrServerError(err) + } + *reply = base64.StdEncoding.EncodeToString(tpExporter.GetCacheBuffer().Bytes()) + return nil +} diff --git a/apier/v1/tp_it_test.go b/apier/v1/tp_it_test.go new file mode 100644 index 000000000..b548b5152 --- /dev/null +++ b/apier/v1/tp_it_test.go @@ -0,0 +1,156 @@ +// +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 v1 + +import ( + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" + "net/rpc" + "net/rpc/jsonrpc" + "path" + "reflect" + "testing" +) + +var ( + tpCfgPath string + tpCfg *config.CGRConfig + tpRPC *rpc.Client + tpDataDir = "/usr/share/cgrates" + tpDelay int + tpConfigDIR string //run tests for specific configuration +) + +var sTestsTP = []func(t *testing.T){ + testTPInitCfg, + testTPResetStorDb, + testTPStartEngine, + testTPRpcConn, + testTPImportTPFromFolderPath, + testTPExportTPToFolder, + testTPKillEngine, +} + +//Test start here +func TestTPITMySql(t *testing.T) { + tpConfigDIR = "tutmysql" + for _, stest := range sTestsTP { + t.Run(tpConfigDIR, stest) + } +} + +func TestTPITMongo(t *testing.T) { + tpConfigDIR = "tutmongo" + for _, stest := range sTestsTP { + t.Run(tpConfigDIR, stest) + } +} + +func TestTPITPG(t *testing.T) { + tpConfigDIR = "tutpostgres" + for _, stest := range sTestsTP { + t.Run(tpConfigDIR, stest) + } +} + +func testTPInitCfg(t *testing.T) { + utils.Logger.Debug("init config") + var err error + tpCfgPath = path.Join(tpDataDir, "conf", "samples", tpConfigDIR) + tpCfg, err = config.NewCGRConfigFromFolder(tpCfgPath) + if err != nil { + t.Error(err) + } + tpCfg.DataFolderPath = tpDataDir // Share DataFolderPath through config towards StoreDb for Flush() + config.SetCgrConfig(tpCfg) + switch tpConfigDIR { + case "tutmongo": // Mongo needs more time to reset db, need to investigate + tpDelay = 2000 + default: + tpDelay = 2000 + } +} + +// Wipe out the cdr database +func testTPResetStorDb(t *testing.T) { + utils.Logger.Debug("ResetStorDB") + if err := engine.InitStorDb(tpCfg); err != nil { + t.Fatal(err) + } +} + +// Start CGR Engine +func testTPStartEngine(t *testing.T) { + utils.Logger.Debug("StartEngine") + if _, err := engine.StopStartEngine(tpCfgPath, tpDelay); err != nil { + t.Fatal(err) + } +} + +// Connect rpc client to rater +func testTPRpcConn(t *testing.T) { + utils.Logger.Debug("RPCCONN") + var err error + tpRPC, err = jsonrpc.Dial("tcp", tpCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal(err) + } +} + +func testTPImportTPFromFolderPath(t *testing.T) { + var reply string + if err := tpRPC.Call("ApierV1.ImportTariffPlanFromFolder", utils.AttrImportTPFromFolder{TPid: "TEST_TPID2", FolderPath: path.Join(tpDataDir, "tariffplans", "tutorial")}, &reply); err != nil { + t.Error("Got error on ApierV1.ImportTarrifPlanFromFolder: ", err.Error()) + } else if reply != utils.OK { + t.Error("Calling ApierV1.ImportTarrifPlanFromFolder got reply: ", reply) + } +} + +func testTPExportTPToFolder(t *testing.T) { + var reply *utils.ExportedTPStats + expectedTPStas := &utils.ExportedTPStats{ + Compressed: true, + ExportPath: "/tmp/", + ExportedFiles: []string{"RatingProfiles.csv", "CdrStats.csv", "Users.csv", "RatingPlans.csv", "Actions.csv", "AccountActions.csv", + "Timings.csv", "SharedGroups.csv", "ActionPlans.csv", "ActionTriggers.cs", "DerivedChargers.csv", "Resources.csv", "Stats.csv", "Thresholds.csv", "Destinations.csv", "Rates.csv", "DestinationRates.csv"}, + } + tpid := "TEST_TPID2" + compress := true + exportPath := "/tmp/" + if err := tpRPC.Call("ApierV1.ExportTPToFolder", &utils.AttrDirExportTP{TPid: &tpid, ExportPath: &exportPath, Compress: &compress}, &reply); err != nil { + t.Error("Got error on ApierV1.ExportTPToFolder: ", err.Error()) + } else if !reflect.DeepEqual(reply.ExportPath, expectedTPStas.ExportPath) { + t.Errorf("Expecting : %+v, received: %+v", expectedTPStas.ExportPath, reply.ExportPath) + } else if !reflect.DeepEqual(reply.Compressed, expectedTPStas.Compressed) { + t.Errorf("Expecting : %+v, received: %+v", expectedTPStas.Compressed, reply.Compressed) + } else if !reflect.DeepEqual(len(reply.ExportedFiles), len(expectedTPStas.ExportedFiles)) { + t.Errorf("Expecting : %+v, received: %+v", len(reply.ExportedFiles), len(expectedTPStas.ExportedFiles)) + } + +} + +func testTPKillEngine(t *testing.T) { + utils.Logger.Debug("KillEngine") + if err := engine.KillEngine(tpDelay); err != nil { + t.Error(err) + } +} diff --git a/apier/v1/tpaccountactions_it_test.go b/apier/v1/tpaccountactions_it_test.go index d0dbe4a18..1f99901c6 100644 --- a/apier/v1/tpaccountactions_it_test.go +++ b/apier/v1/tpaccountactions_it_test.go @@ -73,7 +73,7 @@ func TestTPAccActionsITMongo(t *testing.T) { } } -func TestTTPAccActionsITPG(t *testing.T) { +func TestTPAccActionsITPG(t *testing.T) { tpAccActionsConfigDIR = "tutpostgres" for _, stest := range sTestsTPAccActions { t.Run(tpAccActionsConfigDIR, stest) diff --git a/apier/v2/tp.go b/apier/v2/tp.go deleted file mode 100644 index 2513f87f0..000000000 --- a/apier/v2/tp.go +++ /dev/null @@ -1,99 +0,0 @@ -/* -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 v2 - -import ( - "encoding/base64" - - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -type AttrRemTp struct { - TPid string -} - -func (self *ApierV2) RemTP(attrs AttrRemTp, reply *string) error { - if len(attrs.TPid) == 0 { - return utils.NewErrMandatoryIeMissing("TPid") - } - if err := self.StorDb.RemTpData("", attrs.TPid, nil); err != nil { - return utils.NewErrServerError(err) - } else { - *reply = utils.OK - } - return nil -} - -func (self *ApierV2) ExportTPToFolder(attrs utils.AttrDirExportTP, exported *utils.ExportedTPStats) error { - if attrs.TPid == nil || *attrs.TPid == "" { - return utils.NewErrMandatoryIeMissing("TPid") - } - dir := self.Config.TpExportPath - if attrs.ExportPath != nil { - dir = *attrs.ExportPath - } - fileFormat := utils.CSV - if attrs.FileFormat != nil { - fileFormat = *attrs.FileFormat - } - sep := "," - if attrs.FieldSeparator != nil { - sep = *attrs.FieldSeparator - } - compress := false - if attrs.Compress != nil { - compress = *attrs.Compress - } - tpExporter, err := engine.NewTPExporter(self.StorDb, *attrs.TPid, dir, fileFormat, sep, compress) - if err != nil { - return utils.NewErrServerError(err) - } - if err := tpExporter.Run(); err != nil { - return utils.NewErrServerError(err) - } else { - *exported = *tpExporter.ExportStats() - } - - return nil -} - -func (self *ApierV2) ExportTPToZipString(attrs utils.AttrDirExportTP, reply *string) error { - if attrs.TPid == nil || *attrs.TPid == "" { - return utils.NewErrMandatoryIeMissing("TPid") - } - dir := "" - fileFormat := utils.CSV - if attrs.FileFormat != nil { - fileFormat = *attrs.FileFormat - } - sep := "," - if attrs.FieldSeparator != nil { - sep = *attrs.FieldSeparator - } - tpExporter, err := engine.NewTPExporter(self.StorDb, *attrs.TPid, dir, fileFormat, sep, true) - if err != nil { - return utils.NewErrServerError(err) - } - if err := tpExporter.Run(); err != nil { - return utils.NewErrServerError(err) - } - *reply = base64.StdEncoding.EncodeToString(tpExporter.GetCacheBuffer().Bytes()) - return nil -} diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index 67075343f..358c2588a 100755 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -644,9 +644,9 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err er result = append(result, utils.StatQueueProfilePrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id)) } case utils.AccountActionPlansPrefix: - iter := db.C(colAAp).Find(bson.M{"key": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter() + iter := db.C(colAAp).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter() for iter.Next(&idResult) { - result = append(result, utils.AccountActionPlansPrefix+keyResult.Key) + result = append(result, utils.AccountActionPlansPrefix+idResult.Id) } case utils.TimingsPrefix: iter := db.C(colTmg).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"id": 1}).Iter()