diff --git a/cmd/cgr-migrator/cgr-migrator.go b/cmd/cgr-migrator/cgr-migrator.go index 235b514f3..876ebf73d 100755 --- a/cmd/cgr-migrator/cgr-migrator.go +++ b/cmd/cgr-migrator/cgr-migrator.go @@ -342,6 +342,7 @@ func main() { if err != nil { log.Fatal(err) } + defer m.Close() config.SetCgrConfig(mgrCfg) if exec != nil && *exec != "" { // Run migrator migrstats := make(map[string]int) diff --git a/migrator/action_plan_test.go b/migrator/action_plan_test.go index 8b4135559..9b7722291 100644 --- a/migrator/action_plan_test.go +++ b/migrator/action_plan_test.go @@ -26,8 +26,22 @@ import ( ) func TestV1ActionPlanAsActionPlan(t *testing.T) { - v1ap := &v1ActionPlan{Id: "test", AccountIds: []string{"one"}, Timing: &engine.RateInterval{Timing: new(engine.RITiming)}} - ap := &engine.ActionPlan{Id: "test", AccountIDs: utils.StringMap{"one": true}, ActionTimings: []*engine.ActionTiming{&engine.ActionTiming{Timing: &engine.RateInterval{Timing: new(engine.RITiming)}}}} + v1ap := &v1ActionPlan{ + Id: "test", + AccountIds: []string{"one"}, + Timing: &engine.RateInterval{Timing: new(engine.RITiming)}, + } + ap := &engine.ActionPlan{ + Id: "test", + AccountIDs: utils.StringMap{"one": true}, + ActionTimings: []*engine.ActionTiming{ + &engine.ActionTiming{ + Timing: &engine.RateInterval{ + Timing: new(engine.RITiming), + }, + }, + }, + } newap := v1ap.AsActionPlan() if ap.Id != newap.Id || !reflect.DeepEqual(ap.AccountIDs, newap.AccountIDs) { t.Errorf("Expecting: %+v, received: %+v", *ap, newap) diff --git a/migrator/action_test.go b/migrator/action_test.go index f5f28b7c3..4cbd3f791 100644 --- a/migrator/action_test.go +++ b/migrator/action_test.go @@ -21,12 +21,66 @@ import ( "reflect" "testing" + "github.com/cgrates/cgrates/utils" + "github.com/cgrates/cgrates/engine" ) func TestV1ActionsAsActions(t *testing.T) { - v1act := &v1Action{Id: "", ActionType: "", BalanceType: "", Direction: "INBOUND", ExtraParameters: "", ExpirationString: "", Balance: &v1Balance{}} - act := &engine.Action{Id: "", ActionType: "", ExtraParameters: "", ExpirationString: "", Weight: 0.00, Balance: &engine.BalanceFilter{}} + v1act := &v1Action{ + Id: "", + ActionType: "", + BalanceType: "", + Direction: "INBOUND", + ExtraParameters: "", + ExpirationString: "", + Balance: &v1Balance{}, + } + act := &engine.Action{ + Id: "", + ActionType: "", + ExtraParameters: "", + ExpirationString: "", + Weight: 0.00, + Balance: &engine.BalanceFilter{}, + } + newact := v1act.AsAction() + if !reflect.DeepEqual(act, newact) { + t.Errorf("Expecting: %+v, received: %+v", act, newact) + } +} + +func TestV1ActionsAsActions2(t *testing.T) { + v1act := &v1Action{ + Id: "ID", + ActionType: "*log", + BalanceType: utils.MONETARY, + ExtraParameters: "", + ExpirationString: "", + Balance: &v1Balance{ + Uuid: "UUID1", + Id: utils.MetaDefault, + Value: 10, + Weight: 30, + Category: utils.CALL, + }, + } + + act := &engine.Action{ + Id: "ID", + ActionType: "*log", + ExtraParameters: "", + ExpirationString: "", + Weight: 0.00, + Balance: &engine.BalanceFilter{ + Uuid: utils.StringPointer("UUID1"), + ID: utils.StringPointer(utils.MetaDefault), + Type: utils.StringPointer(utils.MONETARY), + Value: &utils.ValueFormula{Static: 10}, + Weight: utils.Float64Pointer(30), + Categories: utils.StringMapPointer(utils.ParseStringMap(utils.CALL)), + }, + } newact := v1act.AsAction() if !reflect.DeepEqual(act, newact) { t.Errorf("Expecting: %+v, received: %+v", act, newact) diff --git a/migrator/action_trigger_it_test.go b/migrator/action_trigger_it_test.go index c3fcc8346..ed094239e 100644 --- a/migrator/action_trigger_it_test.go +++ b/migrator/action_trigger_it_test.go @@ -20,7 +20,6 @@ along with this program. If not, see package migrator -/* import ( //"flag" "log" @@ -138,23 +137,25 @@ func TestActionTriggerITMoveEncoding2(t *testing.T) { } func testActTrgITConnect(t *testing.T) { - dataDBIn, err := NewMigratorDataDB(actTrgCfgIn.DataDbType, - actTrgCfgIn.DataDbHost, actTrgCfgIn.DataDbPort, actTrgCfgIn.DataDbName, - actTrgCfgIn.DataDbUser, actTrgCfgIn.DataDbPass, actTrgCfgIn.DBDataEncoding, - config.CgrConfig().CacheCfg(), *loadHistorySize) + dataDBIn, err := NewMigratorDataDB(actTrgCfgIn.DataDbCfg().DataDbType, + actTrgCfgIn.DataDbCfg().DataDbHost, actTrgCfgIn.DataDbCfg().DataDbPort, + actTrgCfgIn.DataDbCfg().DataDbName, actTrgCfgIn.DataDbCfg().DataDbUser, + actTrgCfgIn.DataDbCfg().DataDbPass, actTrgCfgIn.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") if err != nil { log.Fatal(err) } - dataDBOut, err := NewMigratorDataDB(actTrgCfgOut.DataDbType, - actTrgCfgOut.DataDbHost, actTrgCfgOut.DataDbPort, actTrgCfgOut.DataDbName, - actTrgCfgOut.DataDbUser, actTrgCfgOut.DataDbPass, actTrgCfgOut.DBDataEncoding, - config.CgrConfig().CacheCfg(), *loadHistorySize) + dataDBOut, err := NewMigratorDataDB(actTrgCfgOut.DataDbCfg().DataDbType, + actTrgCfgOut.DataDbCfg().DataDbHost, actTrgCfgOut.DataDbCfg().DataDbPort, + actTrgCfgOut.DataDbCfg().DataDbName, actTrgCfgOut.DataDbCfg().DataDbUser, + actTrgCfgOut.DataDbCfg().DataDbPass, actTrgCfgOut.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") if err != nil { log.Fatal(err) } actTrgMigrator, err = NewMigrator(dataDBIn, dataDBOut, nil, nil, - false, false, false) + false, false, false, false) if err != nil { log.Fatal(err) } @@ -162,6 +163,7 @@ func testActTrgITConnect(t *testing.T) { func testActTrgITFlush(t *testing.T) { actTrgMigrator.dmOut.DataManager().DataDB().Flush("") + actTrgMigrator.dmIN.DataManager().DataDB().Flush("") if err := engine.SetDBVersions(actTrgMigrator.dmOut.DataManager().DataDB()); err != nil { t.Error("Error ", err.Error()) } @@ -185,10 +187,8 @@ func testActTrgITMigrateAndMove(t *testing.T) { &engine.ActionTrigger{ ID: "Test", Balance: &engine.BalanceFilter{ - Timings: []*engine.RITiming{}, ExpirationDate: utils.TimePointer(tim), Type: utils.StringPointer(utils.MONETARY), - Directions: utils.StringMapPointer(utils.NewStringMap(utils.OUT)), }, ExpirationDate: tim, LastExecutionTime: tim, @@ -202,7 +202,7 @@ func testActTrgITMigrateAndMove(t *testing.T) { switch actActionTrigger { case utils.Migrate: - err := actTrgMigrator.dmIN.setV2ActionTrigger(v1actTrg) + err := actTrgMigrator.dmIN.setV1ActionTriggers(v1actTrg) if err != nil { t.Error("Error when setting v1 ActionTriggers ", err.Error()) } @@ -220,7 +220,7 @@ func testActTrgITMigrateAndMove(t *testing.T) { t.Error("Error when getting ActionTriggers ", err.Error()) } if !reflect.DeepEqual(actTrg, result) { - t.Errorf("Expecting: %+v, received: %+v", actTrg, result) + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(actTrg), utils.ToJSON(result)) } // utils.tojson si verificat case utils.Move: @@ -228,7 +228,7 @@ func testActTrgITMigrateAndMove(t *testing.T) { t.Error("Error when setting ActionTriggers ", err.Error()) } currentVersion := engine.CurrentDataDBVersions() - err := actTrgMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + err := actTrgMigrator.dmIN.DataManager().DataDB().SetVersions(currentVersion, false) if err != nil { t.Error("Error when setting version for ActionTriggers ", err.Error()) } @@ -245,4 +245,3 @@ func testActTrgITMigrateAndMove(t *testing.T) { } } } -*/ diff --git a/migrator/attributes_test.go b/migrator/attributes_test.go index d85ee2d65..530e2e343 100644 --- a/migrator/attributes_test.go +++ b/migrator/attributes_test.go @@ -27,7 +27,7 @@ import ( "github.com/cgrates/cgrates/utils" ) -func Testv1AttributeProfileAsAttributeProfile(t *testing.T) { +func TestV1AttributeProfileAsAttributeProfile(t *testing.T) { var cloneExpTime time.Time expTime := time.Now().Add(time.Duration(20 * time.Minute)) if err := utils.Clone(expTime, &cloneExpTime); err != nil { @@ -66,6 +66,7 @@ func Testv1AttributeProfileAsAttributeProfile(t *testing.T) { &engine.Attribute{ FilterIDs: []string{"*string:FL1:In1"}, FieldName: "FL1", + Type: utils.MetaVariable, Value: config.NewRSRParsersMustCompile("Al1", true, utils.INFIELD_SEP), }, }, @@ -77,3 +78,96 @@ func Testv1AttributeProfileAsAttributeProfile(t *testing.T) { t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(attrPrf), utils.ToJSON(ap)) } } + +func TestV2AttributeProfileAsAttributeProfile(t *testing.T) { + cloneExpTime := time.Now().Add(time.Duration(20 * time.Minute)) + v2Attribute := v2AttributeProfile{ + Tenant: "cgrates.org", + ID: "attributeprofile1", + Contexts: []string{utils.MetaSessionS}, + FilterIDs: []string{"filter1"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + ExpiryTime: cloneExpTime, + }, + Attributes: []*v2Attribute{ + &v2Attribute{ + FieldName: "FL1", + Initial: "In1", + Substitute: config.NewRSRParsersMustCompile("Al1", true, utils.INFIELD_SEP), + Append: true, + }, + }, + Weight: 20, + } + attrPrf := &engine.AttributeProfile{ + Tenant: "cgrates.org", + ID: "attributeprofile1", + Contexts: []string{utils.MetaSessionS}, + FilterIDs: []string{"filter1"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + ExpiryTime: cloneExpTime, + }, + Attributes: []*engine.Attribute{ + &engine.Attribute{ + FilterIDs: []string{"*string:FL1:In1"}, + FieldName: "FL1", + Type: utils.MetaVariable, + Value: config.NewRSRParsersMustCompile("Al1", true, utils.INFIELD_SEP), + }, + }, + Weight: 20, + } + if ap, err := v2Attribute.AsAttributeProfile(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(attrPrf, ap) { + t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(attrPrf), utils.ToJSON(ap)) + } +} + +func TestV3AttributeProfileAsAttributeProfile(t *testing.T) { + cloneExpTime := time.Now().Add(time.Duration(20 * time.Minute)) + v3Attribute := v3AttributeProfile{ + Tenant: "cgrates.org", + ID: "attributeprofile1", + Contexts: []string{utils.MetaSessionS}, + FilterIDs: []string{"filter1"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + ExpiryTime: cloneExpTime, + }, + Attributes: []*v3Attribute{ + &v3Attribute{ + FilterIDs: []string{"*string:FL1:In1"}, + FieldName: "FL1", + Substitute: config.NewRSRParsersMustCompile("Al1", true, utils.INFIELD_SEP), + }, + }, + Weight: 20, + } + attrPrf := &engine.AttributeProfile{ + Tenant: "cgrates.org", + ID: "attributeprofile1", + Contexts: []string{utils.MetaSessionS}, + FilterIDs: []string{"filter1"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + ExpiryTime: cloneExpTime, + }, + Attributes: []*engine.Attribute{ + &engine.Attribute{ + FilterIDs: []string{"*string:FL1:In1"}, + FieldName: "FL1", + Type: utils.MetaVariable, + Value: config.NewRSRParsersMustCompile("Al1", true, utils.INFIELD_SEP), + }, + }, + Weight: 20, + } + if ap, err := v3Attribute.AsAttributeProfile(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(attrPrf, ap) { + t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(attrPrf), utils.ToJSON(ap)) + } +} diff --git a/migrator/cdrs_it_test.go b/migrator/cdrs_it_test.go index b07a155d8..442725d5a 100755 --- a/migrator/cdrs_it_test.go +++ b/migrator/cdrs_it_test.go @@ -133,15 +133,25 @@ func testCdrITMigrateAndMove(t *testing.T) { TOR: utils.VOICE, } v1Cdr := &v1Cdrs{ - CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), - OrderID: 123, ToR: utils.VOICE, OriginID: "dsafdsaf", OriginHost: "192.168.1.1", - Source: utils.UNIT_TEST, RequestType: utils.META_RATED, Tenant: "cgrates.org", - Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), - AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), - RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10), + CGRID: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC).String()), + OrderID: 123, + ToR: utils.VOICE, + OriginID: "dsafdsaf", + OriginHost: "192.168.1.1", + Source: utils.UNIT_TEST, + RequestType: utils.META_RATED, + Tenant: "cgrates.org", + Category: "call", + Account: "1001", + Subject: "1001", + Destination: "1002", + SetupTime: time.Date(2013, 11, 7, 8, 42, 20, 0, time.UTC), + AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + RunID: utils.DEFAULT_RUNID, + Usage: time.Duration(10), ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - Cost: 1.01, Rated: true, + Cost: 1.01, + Rated: true, CostDetails: cc, } var err error diff --git a/migrator/chargers.go b/migrator/chargers.go index 43ed3060d..ae36fa26b 100755 --- a/migrator/chargers.go +++ b/migrator/chargers.go @@ -46,6 +46,10 @@ func (m *Migrator) migrateCurrentCharger() (err error) { if err := m.dmOut.DataManager().SetChargerProfile(cpp, true); err != nil { return err } + if err := m.dmIN.DataManager().RemoveChargerProfile(tenant, + idg, utils.NonTransactional, false); err != nil { + return err + } m.stats[utils.Chargers] += 1 } return diff --git a/migrator/chargers_it_test.go b/migrator/chargers_it_test.go index b27cf33cc..32f513d11 100755 --- a/migrator/chargers_it_test.go +++ b/migrator/chargers_it_test.go @@ -19,3 +19,202 @@ along with this program. If not, see */ package migrator + +import ( + "log" + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + chrgPathIn string + chrgPathOut string + chrgCfgIn *config.CGRConfig + chrgCfgOut *config.CGRConfig + chrgMigrator *Migrator + chrgAction string +) + +var sTestsChrgIT = []func(t *testing.T){ + testChrgITConnect, + testChrgITFlush, + testChrgITMigrateAndMove, +} + +func TestChargersITMove1(t *testing.T) { + var err error + chrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + chrgCfgIn, err = config.NewCGRConfigFromPath(chrgPathIn) + if err != nil { + t.Fatal(err) + } + chrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + chrgCfgOut, err = config.NewCGRConfigFromPath(chrgPathOut) + if err != nil { + t.Fatal(err) + } + chrgAction = utils.Move + for _, stest := range sTestsChrgIT { + t.Run("TestChargersITMove", stest) + } +} + +func TestChargersITMove2(t *testing.T) { + var err error + chrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + chrgCfgIn, err = config.NewCGRConfigFromPath(chrgPathIn) + if err != nil { + t.Fatal(err) + } + chrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmongo") + chrgCfgOut, err = config.NewCGRConfigFromPath(chrgPathOut) + if err != nil { + t.Fatal(err) + } + chrgAction = utils.Move + for _, stest := range sTestsChrgIT { + t.Run("TestChargersITMove", stest) + } +} + +func TestChargersITMoveEncoding(t *testing.T) { + var err error + chrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + chrgCfgIn, err = config.NewCGRConfigFromPath(chrgPathIn) + if err != nil { + t.Fatal(err) + } + chrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmongojson") + chrgCfgOut, err = config.NewCGRConfigFromPath(chrgPathOut) + if err != nil { + t.Fatal(err) + } + chrgAction = utils.Move + for _, stest := range sTestsChrgIT { + t.Run("TestChargersITMoveEncoding", stest) + } +} + +func TestChargersITMoveEncoding2(t *testing.T) { + var err error + chrgPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + chrgCfgIn, err = config.NewCGRConfigFromPath(chrgPathIn) + if err != nil { + t.Fatal(err) + } + chrgPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + chrgCfgOut, err = config.NewCGRConfigFromPath(chrgPathOut) + if err != nil { + t.Fatal(err) + } + chrgAction = utils.Move + for _, stest := range sTestsChrgIT { + t.Run("TestChargersITMoveEncoding2", stest) + } +} + +func testChrgITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(chrgCfgIn.DataDbCfg().DataDbType, + chrgCfgIn.DataDbCfg().DataDbHost, chrgCfgIn.DataDbCfg().DataDbPort, + chrgCfgIn.DataDbCfg().DataDbName, chrgCfgIn.DataDbCfg().DataDbUser, + chrgCfgIn.DataDbCfg().DataDbPass, chrgCfgIn.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(chrgCfgOut.DataDbCfg().DataDbType, + chrgCfgOut.DataDbCfg().DataDbHost, chrgCfgOut.DataDbCfg().DataDbPort, + chrgCfgOut.DataDbCfg().DataDbName, chrgCfgOut.DataDbCfg().DataDbUser, + chrgCfgOut.DataDbCfg().DataDbPass, chrgCfgOut.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + chrgMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testChrgITFlush(t *testing.T) { + if err := chrgMigrator.dmOut.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := chrgMigrator.dmOut.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(chrgMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } + if err := chrgMigrator.dmIN.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := chrgMigrator.dmIN.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(chrgMigrator.dmIN.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testChrgITMigrateAndMove(t *testing.T) { + chrgPrf := &engine.ChargerProfile{ + Tenant: "cgrates.org", + ID: "CHRG_1", + FilterIDs: []string{"*string:Accont:1001"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + }, + AttributeIDs: []string{"ATTR_1"}, + Weight: 20, + } + switch chrgAction { + case utils.Migrate: // for the momment only one version of chargers exists + case utils.Move: + if err := chrgMigrator.dmIN.DataManager().SetChargerProfile(chrgPrf, false); err != nil { + t.Error(err) + } + currentVersion := engine.CurrentDataDBVersions() + err := chrgMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Chargers ", err.Error()) + } + + _, err = chrgMigrator.dmOut.DataManager().GetChargerProfile("cgrates.org", + "CHRG_1", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + + err, _ = chrgMigrator.Migrate([]string{utils.MetaChargers}) + if err != nil { + t.Error("Error when migrating Chargers ", err.Error()) + } + result, err := chrgMigrator.dmOut.DataManager().GetChargerProfile("cgrates.org", + "CHRG_1", false, false, utils.NonTransactional) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, chrgPrf) { + t.Errorf("Expecting: %+v, received: %+v", chrgPrf, result) + } + result, err = chrgMigrator.dmIN.DataManager().GetChargerProfile("cgrates.org", + "CHRG_1", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + } +} diff --git a/migrator/dispatchers_it_test.go b/migrator/dispatchers_it_test.go index c1d227813..98436b16c 100644 --- a/migrator/dispatchers_it_test.go +++ b/migrator/dispatchers_it_test.go @@ -181,9 +181,22 @@ func testDspITMigrateAndMove(t *testing.T) { Strategy: utils.MetaRandom, Weight: 20, } + dspHost := &engine.DispatcherHost{ + Tenant: "cgrates.org", + ID: "ALL", + Conns: []*config.RemoteHost{ + &config.RemoteHost{ + Address: "127.0.0.1", + Transport: utils.MetaJSONrpc, + }, + }, + } if err := dspMigrator.dmIN.DataManager().SetDispatcherProfile(dspPrf, false); err != nil { t.Error(err) } + if err := dspMigrator.dmIN.DataManager().SetDispatcherHost(dspHost); err != nil { + t.Error(err) + } currentVersion := engine.CurrentDataDBVersions() err := dspMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) if err != nil { @@ -213,4 +226,18 @@ func testDspITMigrateAndMove(t *testing.T) { if err != utils.ErrNotFound { t.Error(err) } + + resultHost, err := dspMigrator.dmOut.DataManager().GetDispatcherHost("cgrates.org", + "ALL", false, false, utils.NonTransactional) + if err != nil { + t.Error(err) + } + if !reflect.DeepEqual(resultHost, dspHost) { + t.Errorf("Expecting: %+v, received: %+v", dspHost, resultHost) + } + resultHost, err = dspMigrator.dmIN.DataManager().GetDispatcherHost("cgrates.org", + "ALL", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } } diff --git a/migrator/migrator.go b/migrator/migrator.go index 51012c4e5..f994c4c57 100755 --- a/migrator/migrator.go +++ b/migrator/migrator.go @@ -343,3 +343,19 @@ func (m *Migrator) ensureIndexesStorDB(cols ...string) error { mgo := m.storDBOut.StorDB().(*engine.MongoStorage) return mgo.EnsureIndexes(cols...) } + +// closes all opened DBs +func (m *Migrator) Close() { + if m.dmIN != nil { + m.dmIN.close() + } + if m.dmOut != nil { + m.dmOut.close() + } + if m.storDBIn != nil { + m.storDBIn.close() + } + if m.storDBOut != nil { + m.storDBOut.close() + } +} diff --git a/migrator/migrator_datadb.go b/migrator/migrator_datadb.go index 41dcf669d..4b03daf65 100644 --- a/migrator/migrator_datadb.go +++ b/migrator/migrator_datadb.go @@ -63,4 +63,5 @@ type MigratorDataDB interface { remV3AttributeProfile(tenant, id string) (err error) DataManager() *engine.DataManager + close() } diff --git a/migrator/migrator_stordb.go b/migrator/migrator_stordb.go index 508632220..de3b898dc 100755 --- a/migrator/migrator_stordb.go +++ b/migrator/migrator_stordb.go @@ -31,4 +31,5 @@ type MigratorStorDB interface { setV2SMCost(v2Cost *v2SessionsCost) (err error) remV2SMCost(v2Cost *v2SessionsCost) (err error) StorDB() engine.StorDB + close() } diff --git a/migrator/rating_plan.go b/migrator/rating_plan.go index f656c1fad..bf3f03e2d 100644 --- a/migrator/rating_plan.go +++ b/migrator/rating_plan.go @@ -44,6 +44,9 @@ func (m *Migrator) migrateCurrentRatingPlans() (err error) { if err := m.dmOut.DataManager().SetRatingPlan(rp, utils.NonTransactional); err != nil { return err } + if err := m.dmIN.DataManager().RemoveRatingPlan(idg, utils.NonTransactional); err != nil { + return err + } m.stats[utils.RatingPlan] += 1 } return diff --git a/migrator/rating_plan_it_test.go b/migrator/rating_plan_it_test.go new file mode 100644 index 000000000..0456c37df --- /dev/null +++ b/migrator/rating_plan_it_test.go @@ -0,0 +1,218 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + rtplPathIn string + rtplPathOut string + rtplCfgIn *config.CGRConfig + rtplCfgOut *config.CGRConfig + rtplMigrator *Migrator + rtplAction string +) + +var sTestsRtPlIT = []func(t *testing.T){ + testRtPlITConnect, + testRtPlITFlush, + testRtPlITMigrateAndMove, +} + +func TestRatingPlanITMove1(t *testing.T) { + var err error + rtplPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + rtplCfgIn, err = config.NewCGRConfigFromPath(rtplPathIn) + if err != nil { + t.Fatal(err) + } + rtplPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + rtplCfgOut, err = config.NewCGRConfigFromPath(rtplPathOut) + if err != nil { + t.Fatal(err) + } + rtplAction = utils.Move + for _, stest := range sTestsRtPlIT { + t.Run("TestRatingPlanITMove", stest) + } +} + +func TestRatingPlanITMove2(t *testing.T) { + var err error + rtplPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + rtplCfgIn, err = config.NewCGRConfigFromPath(rtplPathIn) + if err != nil { + t.Fatal(err) + } + rtplPathOut = path.Join(*dataDir, "conf", "samples", "tutmongo") + rtplCfgOut, err = config.NewCGRConfigFromPath(rtplPathOut) + if err != nil { + t.Fatal(err) + } + rtplAction = utils.Move + for _, stest := range sTestsRtPlIT { + t.Run("TestRatingPlanITMove", stest) + } +} + +func TestRatingPlanITMoveEncoding(t *testing.T) { + var err error + rtplPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + rtplCfgIn, err = config.NewCGRConfigFromPath(rtplPathIn) + if err != nil { + t.Fatal(err) + } + rtplPathOut = path.Join(*dataDir, "conf", "samples", "tutmongojson") + rtplCfgOut, err = config.NewCGRConfigFromPath(rtplPathOut) + if err != nil { + t.Fatal(err) + } + rtplAction = utils.Move + for _, stest := range sTestsRtPlIT { + t.Run("TestRatingPlanITMoveEncoding", stest) + } +} + +func TestRatingPlanITMoveEncoding2(t *testing.T) { + var err error + rtplPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + rtplCfgIn, err = config.NewCGRConfigFromPath(rtplPathIn) + if err != nil { + t.Fatal(err) + } + rtplPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + rtplCfgOut, err = config.NewCGRConfigFromPath(rtplPathOut) + if err != nil { + t.Fatal(err) + } + rtplAction = utils.Move + for _, stest := range sTestsRtPlIT { + t.Run("TestRatingPlanITMoveEncoding2", stest) + } +} + +func testRtPlITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(rtplCfgIn.DataDbCfg().DataDbType, + rtplCfgIn.DataDbCfg().DataDbHost, rtplCfgIn.DataDbCfg().DataDbPort, + rtplCfgIn.DataDbCfg().DataDbName, rtplCfgIn.DataDbCfg().DataDbUser, + rtplCfgIn.DataDbCfg().DataDbPass, rtplCfgIn.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(rtplCfgOut.DataDbCfg().DataDbType, + rtplCfgOut.DataDbCfg().DataDbHost, rtplCfgOut.DataDbCfg().DataDbPort, + rtplCfgOut.DataDbCfg().DataDbName, rtplCfgOut.DataDbCfg().DataDbUser, + rtplCfgOut.DataDbCfg().DataDbPass, rtplCfgOut.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + rtplMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testRtPlITFlush(t *testing.T) { + if err := rtplMigrator.dmOut.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := rtplMigrator.dmOut.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(rtplMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } + if err := rtplMigrator.dmIN.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := rtplMigrator.dmIN.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(rtplMigrator.dmIN.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testRtPlITMigrateAndMove(t *testing.T) { + rtplPlan := &engine.RatingPlan{ + Id: "RT_PLAN1", + Timings: map[string]*engine.RITiming{}, + Ratings: map[string]*engine.RIRate{ + "asjkilj": &engine.RIRate{ + ConnectFee: 10, + RoundingMethod: utils.ROUNDING_UP, + RoundingDecimals: 1, + MaxCost: 10, + }, + }, + DestinationRates: map[string]engine.RPRateList{}, + } + switch rtplAction { + case utils.Migrate: // for the momment only one version of rating plans exists + case utils.Move: + if err := rtplMigrator.dmIN.DataManager().SetRatingPlan(rtplPlan, utils.NonTransactional); err != nil { + t.Error(err) + } + currentVersion := engine.CurrentDataDBVersions() + err := rtplMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for RatingPlan ", err.Error()) + } + + _, err = rtplMigrator.dmOut.DataManager().GetRatingPlan("RT_PLAN1", true, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + + err, _ = rtplMigrator.Migrate([]string{utils.MetaRatingPlans}) + if err != nil { + t.Error("Error when migrating RatingPlan ", err.Error()) + } + result, err := rtplMigrator.dmOut.DataManager().GetRatingPlan("RT_PLAN1", true, utils.NonTransactional) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, rtplPlan) { + t.Errorf("Expecting: %+v, received: %+v", rtplPlan, result) + } + result, err = rtplMigrator.dmIN.DataManager().GetRatingPlan("RT_PLAN1", true, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + } +} diff --git a/migrator/rating_profile.go b/migrator/rating_profile.go index 18e1226a0..871bdc910 100644 --- a/migrator/rating_profile.go +++ b/migrator/rating_profile.go @@ -44,6 +44,9 @@ func (m *Migrator) migrateCurrentRatingProfiles() (err error) { if err := m.dmOut.DataManager().SetRatingProfile(rp, utils.NonTransactional); err != nil { return err } + if err := m.dmIN.DataManager().RemoveRatingProfile(idg, utils.NonTransactional); err != nil { + return err + } m.stats[utils.RatingProfile] += 1 } return diff --git a/migrator/rating_profile_it_test.go b/migrator/rating_profile_it_test.go new file mode 100644 index 000000000..9663e4d68 --- /dev/null +++ b/migrator/rating_profile_it_test.go @@ -0,0 +1,220 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + rtprflPathIn string + rtprflPathOut string + rtprflCfgIn *config.CGRConfig + rtprflCfgOut *config.CGRConfig + rtprflMigrator *Migrator + rtprflAction string +) + +var sTestsRtPrfIT = []func(t *testing.T){ + testRtPrfITConnect, + testRtPrfITFlush, + testRtPrfITMigrateAndMove, +} + +func TestRatingProfileITMove1(t *testing.T) { + var err error + rtprflPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + rtprflCfgIn, err = config.NewCGRConfigFromPath(rtprflPathIn) + if err != nil { + t.Fatal(err) + } + rtprflPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + rtprflCfgOut, err = config.NewCGRConfigFromPath(rtprflPathOut) + if err != nil { + t.Fatal(err) + } + rtprflAction = utils.Move + for _, stest := range sTestsRtPrfIT { + t.Run("TestRatingProfileITMove", stest) + } + rtprflMigrator.Close() +} + +func TestRatingProfileITMove2(t *testing.T) { + var err error + rtprflPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + rtprflCfgIn, err = config.NewCGRConfigFromPath(rtprflPathIn) + if err != nil { + t.Fatal(err) + } + rtprflPathOut = path.Join(*dataDir, "conf", "samples", "tutmongo") + rtprflCfgOut, err = config.NewCGRConfigFromPath(rtprflPathOut) + if err != nil { + t.Fatal(err) + } + rtprflAction = utils.Move + for _, stest := range sTestsRtPrfIT { + t.Run("TestRatingProfileITMove", stest) + } + rtprflMigrator.Close() +} + +func TestRatingProfileITMoveEncoding(t *testing.T) { + var err error + rtprflPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + rtprflCfgIn, err = config.NewCGRConfigFromPath(rtprflPathIn) + if err != nil { + t.Fatal(err) + } + rtprflPathOut = path.Join(*dataDir, "conf", "samples", "tutmongojson") + rtprflCfgOut, err = config.NewCGRConfigFromPath(rtprflPathOut) + if err != nil { + t.Fatal(err) + } + rtprflAction = utils.Move + for _, stest := range sTestsRtPrfIT { + t.Run("TestRatingProfileITMoveEncoding", stest) + } + rtprflMigrator.Close() +} + +func TestRatingProfileITMoveEncoding2(t *testing.T) { + var err error + rtprflPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + rtprflCfgIn, err = config.NewCGRConfigFromPath(rtprflPathIn) + if err != nil { + t.Fatal(err) + } + rtprflPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + rtprflCfgOut, err = config.NewCGRConfigFromPath(rtprflPathOut) + if err != nil { + t.Fatal(err) + } + rtprflAction = utils.Move + for _, stest := range sTestsRtPrfIT { + t.Run("TestRatingProfileITMoveEncoding2", stest) + } + rtprflMigrator.Close() +} + +func testRtPrfITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(rtprflCfgIn.DataDbCfg().DataDbType, + rtprflCfgIn.DataDbCfg().DataDbHost, rtprflCfgIn.DataDbCfg().DataDbPort, + rtprflCfgIn.DataDbCfg().DataDbName, rtprflCfgIn.DataDbCfg().DataDbUser, + rtprflCfgIn.DataDbCfg().DataDbPass, rtprflCfgIn.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(rtprflCfgOut.DataDbCfg().DataDbType, + rtprflCfgOut.DataDbCfg().DataDbHost, rtprflCfgOut.DataDbCfg().DataDbPort, + rtprflCfgOut.DataDbCfg().DataDbName, rtprflCfgOut.DataDbCfg().DataDbUser, + rtprflCfgOut.DataDbCfg().DataDbPass, rtprflCfgOut.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + rtprflMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testRtPrfITFlush(t *testing.T) { + if err := rtprflMigrator.dmOut.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := rtprflMigrator.dmOut.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(rtprflMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } + if err := rtprflMigrator.dmIN.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := rtprflMigrator.dmIN.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(rtprflMigrator.dmIN.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testRtPrfITMigrateAndMove(t *testing.T) { + rtprfl := &engine.RatingProfile{ + Id: "RT_Profile", + RatingPlanActivations: engine.RatingPlanActivations{ + &engine.RatingPlanActivation{ + ActivationTime: time.Now().Round(time.Second).UTC(), + RatingPlanId: "RP_PLAN1", + FallbackKeys: []string{"1001"}, + }, + }, + } + switch rtprflAction { + case utils.Migrate: // for the momment only one version of rating plans exists + case utils.Move: + if err := rtprflMigrator.dmIN.DataManager().SetRatingProfile(rtprfl, utils.NonTransactional); err != nil { + t.Error(err) + } + currentVersion := engine.CurrentDataDBVersions() + err := rtprflMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for RatingProfile ", err.Error()) + } + + _, err = rtprflMigrator.dmOut.DataManager().GetRatingProfile("RT_Profile", true, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + + err, _ = rtprflMigrator.Migrate([]string{utils.MetaRatingProfiles}) + if err != nil { + t.Error("Error when migrating RatingProfile ", err.Error()) + } + result, err := rtprflMigrator.dmOut.DataManager().GetRatingProfile("RT_Profile", true, utils.NonTransactional) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, rtprfl) { + t.Errorf("Expecting: %+v, received: %+v", rtprfl, result) + } + result, err = rtprflMigrator.dmIN.DataManager().GetRatingProfile("RT_Profile", true, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + } +} diff --git a/migrator/resource.go b/migrator/resource.go index a9acc7e42..6f46a1c95 100644 --- a/migrator/resource.go +++ b/migrator/resource.go @@ -46,6 +46,9 @@ func (m *Migrator) migrateCurrentResource() (err error) { if err := m.dmOut.DataManager().SetResourceProfile(res, true); err != nil { return err } + if err := m.dmIN.DataManager().RemoveResourceProfile(tenant, idg, utils.NonTransactional, false); err != nil { + return err + } m.stats[utils.Resource] += 1 } return diff --git a/migrator/resource_it_test.go b/migrator/resource_it_test.go new file mode 100644 index 000000000..0b2c2a8d8 --- /dev/null +++ b/migrator/resource_it_test.go @@ -0,0 +1,219 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + resPathIn string + resPathOut string + resCfgIn *config.CGRConfig + resCfgOut *config.CGRConfig + resMigrator *Migrator + resAction string +) + +var sTestsResIT = []func(t *testing.T){ + testResITConnect, + testResITFlush, + testResITMigrateAndMove, +} + +func TestResourceITMove1(t *testing.T) { + var err error + resPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + resCfgIn, err = config.NewCGRConfigFromPath(resPathIn) + if err != nil { + t.Fatal(err) + } + resPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + resCfgOut, err = config.NewCGRConfigFromPath(resPathOut) + if err != nil { + t.Fatal(err) + } + resAction = utils.Move + for _, stest := range sTestsResIT { + t.Run("TestResourceITMove", stest) + } + resMigrator.Close() +} + +func TestResourceITMove2(t *testing.T) { + var err error + resPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + resCfgIn, err = config.NewCGRConfigFromPath(resPathIn) + if err != nil { + t.Fatal(err) + } + resPathOut = path.Join(*dataDir, "conf", "samples", "tutmongo") + resCfgOut, err = config.NewCGRConfigFromPath(resPathOut) + if err != nil { + t.Fatal(err) + } + resAction = utils.Move + for _, stest := range sTestsResIT { + t.Run("TestResourceITMove", stest) + } + resMigrator.Close() +} + +func TestResourceITMoveEncoding(t *testing.T) { + var err error + resPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + resCfgIn, err = config.NewCGRConfigFromPath(resPathIn) + if err != nil { + t.Fatal(err) + } + resPathOut = path.Join(*dataDir, "conf", "samples", "tutmongojson") + resCfgOut, err = config.NewCGRConfigFromPath(resPathOut) + if err != nil { + t.Fatal(err) + } + resAction = utils.Move + for _, stest := range sTestsResIT { + t.Run("TestResourceITMoveEncoding", stest) + } + resMigrator.Close() +} + +func TestResourceITMoveEncoding2(t *testing.T) { + var err error + resPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + resCfgIn, err = config.NewCGRConfigFromPath(resPathIn) + if err != nil { + t.Fatal(err) + } + resPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + resCfgOut, err = config.NewCGRConfigFromPath(resPathOut) + if err != nil { + t.Fatal(err) + } + resAction = utils.Move + for _, stest := range sTestsResIT { + t.Run("TestResourceITMoveEncoding2", stest) + } + resMigrator.Close() +} + +func testResITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(resCfgIn.DataDbCfg().DataDbType, + resCfgIn.DataDbCfg().DataDbHost, resCfgIn.DataDbCfg().DataDbPort, + resCfgIn.DataDbCfg().DataDbName, resCfgIn.DataDbCfg().DataDbUser, + resCfgIn.DataDbCfg().DataDbPass, resCfgIn.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(resCfgOut.DataDbCfg().DataDbType, + resCfgOut.DataDbCfg().DataDbHost, resCfgOut.DataDbCfg().DataDbPort, + resCfgOut.DataDbCfg().DataDbName, resCfgOut.DataDbCfg().DataDbUser, + resCfgOut.DataDbCfg().DataDbPass, resCfgOut.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + resMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testResITFlush(t *testing.T) { + if err := resMigrator.dmOut.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := resMigrator.dmOut.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(resMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } + if err := resMigrator.dmIN.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := resMigrator.dmIN.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(resMigrator.dmIN.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testResITMigrateAndMove(t *testing.T) { + resPrfl := &engine.ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES1", + FilterIDs: []string{"*string:~Account:1001"}, + UsageTTL: time.Second, + Limit: 1, + Weight: 10, + ThresholdIDs: []string{"TH1"}, + } + switch resAction { + case utils.Migrate: // for the momment only one version of rating plans exists + case utils.Move: + if err := resMigrator.dmIN.DataManager().SetResourceProfile(resPrfl, true); err != nil { + t.Error(err) + } + currentVersion := engine.CurrentDataDBVersions() + err := resMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Resource ", err.Error()) + } + + _, err = resMigrator.dmOut.DataManager().GetResourceProfile("cgrates.org", "RES1", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + + err, _ = resMigrator.Migrate([]string{utils.MetaResources}) + if err != nil { + t.Error("Error when migrating Resource ", err.Error()) + } + result, err := resMigrator.dmOut.DataManager().GetResourceProfile("cgrates.org", "RES1", false, false, utils.NonTransactional) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, resPrfl) { + t.Errorf("Expecting: %+v, received: %+v", resPrfl, result) + } + result, err = resMigrator.dmIN.DataManager().GetResourceProfile("cgrates.org", "RES1", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + } +} diff --git a/migrator/session_costs_test.go b/migrator/session_costs_test.go new file mode 100644 index 000000000..001fa4e44 --- /dev/null +++ b/migrator/session_costs_test.go @@ -0,0 +1,95 @@ +/* +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 migrator + +import ( + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +func TestV2toV3Cost(t *testing.T) { + cc := &engine.CallCost{ + Category: utils.CALL, + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + TOR: "ToR", + Cost: 10, + Timespans: engine.TimeSpans{ + &engine.TimeSpan{ + TimeStart: time.Now(), + TimeEnd: time.Now().Add(time.Minute), + Cost: 10, + RateInterval: &engine.RateInterval{ + Rating: &engine.RIRate{ + Rates: engine.RateGroups{ + &engine.Rate{ + GroupIntervalStart: 0, + Value: 100, + RateIncrement: 10 * time.Second, + RateUnit: time.Second, + }, + }, + }, + }, + }, + }, + RatedUsage: 10, + AccountSummary: &engine.AccountSummary{ + Tenant: "cgrates.org", + ID: "1001", + BalanceSummaries: []*engine.BalanceSummary{ + &engine.BalanceSummary{ + UUID: "UUID", + ID: "First", + Type: utils.MONETARY, + Value: 10, + }, + }, + }, + } + sv2 := v2SessionsCost{ + CGRID: "CGRID", + RunID: utils.MetaDefault, + OriginHost: utils.FreeSWITCHAgent, + OriginID: "Origin1", + CostSource: utils.MetaSessionS, + Usage: time.Second, + CostDetails: cc, + } + sv3 := &engine.SMCost{ + CGRID: "CGRID", + RunID: utils.MetaDefault, + OriginHost: utils.FreeSWITCHAgent, + OriginID: "Origin1", + Usage: time.Second, + CostSource: utils.MetaSessionS, + CostDetails: engine.NewEventCostFromCallCost(cc, "CGRID", utils.MetaDefault), + } + rply := sv2.V2toV3Cost() + rply.CostDetails = sv3.CostDetails + if !reflect.DeepEqual(sv3, rply) { + t.Errorf("Expected: %s ,received: %s", utils.ToJSON(sv3), utils.ToJSON(rply)) + } +} diff --git a/migrator/storage_map_datadb.go b/migrator/storage_map_datadb.go index 0e4936372..496a2f74d 100755 --- a/migrator/storage_map_datadb.go +++ b/migrator/storage_map_datadb.go @@ -246,3 +246,5 @@ func (v1ms *mapMigrator) setV3AttributeProfile(x *v3AttributeProfile) (err error func (v1ms *mapMigrator) remV3AttributeProfile(tenant, id string) (err error) { return utils.ErrNotImplemented } + +func (v1ms *mapMigrator) close() {} diff --git a/migrator/storage_map_stordb.go b/migrator/storage_map_stordb.go index f866b47c2..ce52b3bd3 100755 --- a/migrator/storage_map_stordb.go +++ b/migrator/storage_map_stordb.go @@ -37,6 +37,8 @@ type mapStorDBMigrator struct { qryIdx *int } +func (mpMig *mapStorDBMigrator) close() {} + func (mpMig *mapStorDBMigrator) StorDB() engine.StorDB { return *mpMig.storDB } diff --git a/migrator/storage_mongo_datadb.go b/migrator/storage_mongo_datadb.go index 35ca71eb5..2cabac931 100644 --- a/migrator/storage_mongo_datadb.go +++ b/migrator/storage_mongo_datadb.go @@ -59,6 +59,10 @@ func newMongoMigrator(dm *engine.DataManager) (mgoMig *mongoMigrator) { } } +func (mgoMig *mongoMigrator) close() { + mgoMig.mgoDB.Close() +} + func (mgoMig *mongoMigrator) DataManager() *engine.DataManager { return mgoMig.dm } @@ -202,12 +206,35 @@ func (v1ms *mongoMigrator) setV1Actions(x *v1Actions) (err error) { //ActionTriggers methods //get func (v1ms *mongoMigrator) getV1ActionTriggers() (v1acts *v1ActionTriggers, err error) { - return nil, utils.ErrNotImplemented + if v1ms.cursor == nil { + var cursor mongo.Cursor + cursor, err = v1ms.mgoDB.DB().Collection(v1ActionTriggersCol).Find(v1ms.mgoDB.GetContext(), bson.D{}) + if err != nil { + return nil, err + } + v1ms.cursor = &cursor + } + if !(*v1ms.cursor).Next(v1ms.mgoDB.GetContext()) { + (*v1ms.cursor).Close(v1ms.mgoDB.GetContext()) + v1ms.cursor = nil + return nil, utils.ErrNoMoreData + } + v1act := new(v1ActionTrigger) + if err := (*v1ms.cursor).Decode(v1act); err != nil { + return nil, err + } + return &v1ActionTriggers{v1act}, nil } //set -func (v1ms *mongoMigrator) setV1ActionTriggers(x *v1ActionTriggers) (err error) { - return utils.ErrNotImplemented +func (v1ms *mongoMigrator) setV1ActionTriggers(act *v1ActionTriggers) (err error) { + for _, x := range *act { + _, err = v1ms.mgoDB.DB().Collection(v1ActionTriggersCol).InsertOne(v1ms.mgoDB.GetContext(), *x) + if err != nil { + return err + } + } + return } //Actions methods diff --git a/migrator/storage_mongo_stordb.go b/migrator/storage_mongo_stordb.go index 3feae80b0..e02c748c2 100644 --- a/migrator/storage_mongo_stordb.go +++ b/migrator/storage_mongo_stordb.go @@ -39,6 +39,10 @@ type mongoStorDBMigrator struct { cursor *mongo.Cursor } +func (mgoMig *mongoStorDBMigrator) close() { + mgoMig.mgoDB.Close() +} + func (mgoMig *mongoStorDBMigrator) StorDB() engine.StorDB { return *mgoMig.storDB } diff --git a/migrator/storage_redis.go b/migrator/storage_redis.go index b45477b40..973dcb07d 100644 --- a/migrator/storage_redis.go +++ b/migrator/storage_redis.go @@ -44,6 +44,10 @@ func newRedisMigrator(dm *engine.DataManager) (rM *redisMigrator) { } } +func (rdsMig *redisMigrator) close() { + rdsMig.rds.Close() +} + func (rdsMig *redisMigrator) DataManager() *engine.DataManager { return rdsMig.dm } diff --git a/migrator/storage_sql.go b/migrator/storage_sql.go index c9c249a1a..2a1e87deb 100755 --- a/migrator/storage_sql.go +++ b/migrator/storage_sql.go @@ -41,6 +41,10 @@ type migratorSQL struct { rowIter *sql.Rows } +func (sqlMig *migratorSQL) close() { + sqlMig.sqlStorage.Close() +} + func (sqlMig *migratorSQL) StorDB() engine.StorDB { return *sqlMig.storDB } diff --git a/migrator/suppliers.go b/migrator/suppliers.go index fefb4e261..d2e422fde 100644 --- a/migrator/suppliers.go +++ b/migrator/suppliers.go @@ -35,7 +35,7 @@ func (m *Migrator) migrateCurrentSupplierProfile() (err error) { return err } for _, id := range ids { - idg := strings.TrimPrefix(id, utils.SupplierProfilePrefix) + idg := strings.TrimPrefix(id, utils.SupplierProfilePrefix+tenant+":") splp, err := m.dmIN.DataManager().GetSupplierProfile(tenant, idg, false, false, utils.NonTransactional) if err != nil { return err @@ -46,6 +46,9 @@ func (m *Migrator) migrateCurrentSupplierProfile() (err error) { if err := m.dmOut.DataManager().SetSupplierProfile(splp, true); err != nil { return err } + if err := m.dmIN.DataManager().RemoveSupplierProfile(tenant, idg, utils.NonTransactional, true); err != nil { + return err + } m.stats[utils.Suppliers] += 1 } return diff --git a/migrator/suppliers_it_test.go b/migrator/suppliers_it_test.go new file mode 100644 index 000000000..2e59c1a57 --- /dev/null +++ b/migrator/suppliers_it_test.go @@ -0,0 +1,230 @@ +// +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 migrator + +import ( + "log" + "path" + "reflect" + "testing" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + supPathIn string + supPathOut string + supCfgIn *config.CGRConfig + supCfgOut *config.CGRConfig + supMigrator *Migrator + supAction string +) + +var sTestsSupIT = []func(t *testing.T){ + testSupITConnect, + testSupITFlush, + testSupITMigrateAndMove, +} + +func TestSuppliersITMove1(t *testing.T) { + var err error + supPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + supCfgIn, err = config.NewCGRConfigFromPath(supPathIn) + if err != nil { + t.Fatal(err) + } + supPathOut = path.Join(*dataDir, "conf", "samples", "tutmysql") + supCfgOut, err = config.NewCGRConfigFromPath(supPathOut) + if err != nil { + t.Fatal(err) + } + supAction = utils.Move + for _, stest := range sTestsSupIT { + t.Run("TestSuppliersITMove", stest) + } + supMigrator.Close() +} + +func TestSuppliersITMove2(t *testing.T) { + var err error + supPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + supCfgIn, err = config.NewCGRConfigFromPath(supPathIn) + if err != nil { + t.Fatal(err) + } + supPathOut = path.Join(*dataDir, "conf", "samples", "tutmongo") + supCfgOut, err = config.NewCGRConfigFromPath(supPathOut) + if err != nil { + t.Fatal(err) + } + supAction = utils.Move + for _, stest := range sTestsSupIT { + t.Run("TestSuppliersITMove", stest) + } + supMigrator.Close() +} + +func TestSuppliersITMoveEncoding(t *testing.T) { + var err error + supPathIn = path.Join(*dataDir, "conf", "samples", "tutmongo") + supCfgIn, err = config.NewCGRConfigFromPath(supPathIn) + if err != nil { + t.Fatal(err) + } + supPathOut = path.Join(*dataDir, "conf", "samples", "tutmongojson") + supCfgOut, err = config.NewCGRConfigFromPath(supPathOut) + if err != nil { + t.Fatal(err) + } + supAction = utils.Move + for _, stest := range sTestsSupIT { + t.Run("TestSuppliersITMoveEncoding", stest) + } + supMigrator.Close() +} + +func TestSuppliersITMoveEncoding2(t *testing.T) { + var err error + supPathIn = path.Join(*dataDir, "conf", "samples", "tutmysql") + supCfgIn, err = config.NewCGRConfigFromPath(supPathIn) + if err != nil { + t.Fatal(err) + } + supPathOut = path.Join(*dataDir, "conf", "samples", "tutmysqljson") + supCfgOut, err = config.NewCGRConfigFromPath(supPathOut) + if err != nil { + t.Fatal(err) + } + supAction = utils.Move + for _, stest := range sTestsSupIT { + t.Run("TestSuppliersITMoveEncoding2", stest) + } + supMigrator.Close() +} + +func testSupITConnect(t *testing.T) { + dataDBIn, err := NewMigratorDataDB(supCfgIn.DataDbCfg().DataDbType, + supCfgIn.DataDbCfg().DataDbHost, supCfgIn.DataDbCfg().DataDbPort, + supCfgIn.DataDbCfg().DataDbName, supCfgIn.DataDbCfg().DataDbUser, + supCfgIn.DataDbCfg().DataDbPass, supCfgIn.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + dataDBOut, err := NewMigratorDataDB(supCfgOut.DataDbCfg().DataDbType, + supCfgOut.DataDbCfg().DataDbHost, supCfgOut.DataDbCfg().DataDbPort, + supCfgOut.DataDbCfg().DataDbName, supCfgOut.DataDbCfg().DataDbUser, + supCfgOut.DataDbCfg().DataDbPass, supCfgOut.GeneralCfg().DBDataEncoding, + config.CgrConfig().CacheCfg(), "") + if err != nil { + log.Fatal(err) + } + supMigrator, err = NewMigrator(dataDBIn, dataDBOut, + nil, nil, + false, false, false, false) + if err != nil { + log.Fatal(err) + } +} + +func testSupITFlush(t *testing.T) { + if err := supMigrator.dmOut.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := supMigrator.dmOut.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(supMigrator.dmOut.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } + if err := supMigrator.dmIN.DataManager().DataDB().Flush(""); err != nil { + t.Error(err) + } + if isEmpty, err := supMigrator.dmIN.DataManager().DataDB().IsDBEmpty(); err != nil { + t.Error(err) + } else if isEmpty != true { + t.Errorf("\nExpecting: true got :%+v", isEmpty) + } + if err := engine.SetDBVersions(supMigrator.dmIN.DataManager().DataDB()); err != nil { + t.Error("Error ", err.Error()) + } +} + +func testSupITMigrateAndMove(t *testing.T) { + supPrfl := &engine.SupplierProfile{ + Tenant: "cgrates.org", + ID: "SUP1", + FilterIDs: []string{"*string:~Account:1001"}, + Weight: 10, + Sorting: utils.MetaQOS, + SortingParameters: []string{}, + Suppliers: []*engine.Supplier{ + &engine.Supplier{ + ID: "Sup", + FilterIDs: []string{}, + AccountIDs: []string{"1001"}, + RatingPlanIDs: []string{"RT_PLAN1"}, + ResourceIDs: []string{"RES1"}, + Weight: 10, + }, + }, + } + switch supAction { + case utils.Migrate: // for the momment only one version of rating plans exists + case utils.Move: + if err := supMigrator.dmIN.DataManager().SetSupplierProfile(supPrfl, true); err != nil { + t.Error(err) + } + if _, err := supMigrator.dmIN.DataManager().GetSupplierProfile("cgrates.org", "SUP1", false, false, utils.NonTransactional); err != nil { + t.Error(err) + } + currentVersion := engine.CurrentDataDBVersions() + err := supMigrator.dmOut.DataManager().DataDB().SetVersions(currentVersion, false) + if err != nil { + t.Error("Error when setting version for Suppliers ", err.Error()) + } + + _, err = supMigrator.dmOut.DataManager().GetSupplierProfile("cgrates.org", "SUP1", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + + err, _ = supMigrator.Migrate([]string{utils.MetaSuppliers}) + if err != nil { + t.Error("Error when migrating Suppliers ", err.Error()) + } + result, err := supMigrator.dmOut.DataManager().GetSupplierProfile("cgrates.org", "SUP1", false, false, utils.NonTransactional) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(result, supPrfl) { + t.Errorf("Expecting: %+v, received: %+v", supPrfl, result) + } + result, err = supMigrator.dmIN.DataManager().GetSupplierProfile("cgrates.org", "SUP1", false, false, utils.NonTransactional) + if err != utils.ErrNotFound { + t.Error(err) + } + } +}