diff --git a/actions/log.go b/actions/log.go index 6134e7be5..3af1a6a74 100644 --- a/actions/log.go +++ b/actions/log.go @@ -75,14 +75,8 @@ func (aL *actCDRLog) execute(_ context.Context, data utils.MapStorage, _ string) reqNm := utils.MapStorage(data[utils.MetaReq].(map[string]interface{})).Clone() optsMS := utils.MapStorage(data[utils.MetaOpts].(map[string]interface{})).Clone() - optsNm := utils.NewOrderedNavigableMap() - for key, val := range optsMS { - optsNm.Set(utils.NewFullPath(key, utils.NestingSep), utils.NewNMData(val)) - } - oNm := map[string]*utils.OrderedNavigableMap{ - utils.MetaCDR: utils.NewOrderedNavigableMap(), - utils.MetaOpts: optsNm, + utils.MetaCDR: utils.NewOrderedNavigableMap(), } // construct an AgentRequest so we can build the reply and send it to CDRServer cdrLogReq := engine.NewEventRequest(reqNm, nil, optsMS, nil, aL.config.GeneralCfg().DefaultTenant, @@ -97,6 +91,6 @@ func (aL *actCDRLog) execute(_ context.Context, data utils.MapStorage, _ string) &engine.ArgV1ProcessEvent{ Flags: []string{utils.ConcatenatedKey(utils.MetaChargers, utils.FalseStr)}, // do not try to get the chargers for cdrlog CGREvent: *config.NMAsCGREvent(cdrLogReq.OrdNavMP[utils.MetaCDR], cdrLogReq.Tenant, - utils.NestingSep, cdrLogReq.OrdNavMP[utils.MetaOpts]), + utils.NestingSep, optsMS), }, &rply) } diff --git a/agents/agentreq.go b/agents/agentreq.go index 6b8a71760..636d2f653 100644 --- a/agents/agentreq.go +++ b/agents/agentreq.go @@ -33,24 +33,24 @@ import ( // NewAgentRequest returns a new AgentRequest func NewAgentRequest(req utils.DataProvider, - vars utils.NavigableMap, - cgrRply *utils.NavigableMap, - rply, opts *utils.OrderedNavigableMap, + vars, cgrRply *utils.DataNode, + rply *utils.OrderedNavigableMap, + opts utils.MapStorage, tntTpl config.RSRParsers, dfltTenant, timezone string, filterS *engine.FilterS, header, trailer utils.DataProvider) (ar *AgentRequest) { if cgrRply == nil { - cgrRply = &utils.NavigableMap{} + cgrRply = &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} } if vars == nil { - vars = make(utils.NavigableMap) + vars = &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} } if rply == nil { rply = utils.NewOrderedNavigableMap() } if opts == nil { - opts = utils.NewOrderedNavigableMap() + opts = make(utils.MapStorage) } ar = &AgentRequest{ Request: req, @@ -67,14 +67,10 @@ func NewAgentRequest(req utils.DataProvider, Opts: opts, Cfg: config.CgrConfig().GetDataProvider(), } - if tntTpl != nil { - if tntIf, err := ar.ParseField( - &config.FCTemplate{Type: utils.MetaComposed, - Value: tntTpl}); err == nil && tntIf.(string) != "" { - ar.Tenant = tntIf.(string) - } + if tnt, err := tntTpl.ParseDataProvider(ar); err == nil && tnt != utils.EmptyString { + ar.Tenant = tnt } - ar.Vars.Set(utils.PathItems{{Field: utils.NodeID}}, utils.NewNMData(config.CgrConfig().GeneralCfg().NodeID)) + ar.Vars.Set([]string{utils.NodeID}, config.CgrConfig().GeneralCfg().NodeID) return } @@ -82,9 +78,9 @@ func NewAgentRequest(req utils.DataProvider, // implements utils.DataProvider so we can pass it to filters type AgentRequest struct { Request utils.DataProvider // request - Vars utils.NavigableMap // shared data + Vars *utils.DataNode // shared data CGRRequest *utils.OrderedNavigableMap // Used in reply to access the request that was send - CGRReply *utils.NavigableMap + CGRReply *utils.DataNode Reply *utils.OrderedNavigableMap Tenant string Timezone string @@ -92,8 +88,8 @@ type AgentRequest struct { Header utils.DataProvider Trailer utils.DataProvider diamreq *utils.OrderedNavigableMap // used in case of building requests (ie. DisconnectSession) - tmp utils.NavigableMap // used in case you want to store temporary items and access them later - Opts *utils.OrderedNavigableMap + tmp *utils.DataNode // used in case you want to store temporary items and access them later + Opts utils.MapStorage Cfg utils.DataProvider } @@ -144,31 +140,11 @@ func (ar *AgentRequest) FieldAsInterface(fldPath []string) (val interface{}, err if err != nil { return } - if nmItems, isNMItems := val.(*utils.NMSlice); isNMItems { // special handling of NMItems, take the last value out of it - val = (*nmItems)[len(*nmItems)-1].Interface() - } - return -} - -// Field implements utils.NMInterface -func (ar *AgentRequest) Field(fldPath utils.PathItems) (val utils.NMInterface, err error) { - switch fldPath[0].Field { - default: - return nil, fmt.Errorf("unsupported field prefix: <%s>", fldPath[0]) - case utils.MetaVars: - val, err = ar.Vars.Field(fldPath[1:]) - case utils.MetaCgreq: - val, err = ar.CGRRequest.Field(fldPath[1:]) - case utils.MetaCgrep: - val, err = ar.CGRReply.Field(fldPath[1:]) - case utils.MetaDiamreq: - val, err = ar.diamreq.Field(fldPath[1:]) - case utils.MetaRep: - val, err = ar.Reply.Field(fldPath[1:]) - case utils.MetaTmp: - val, err = ar.tmp.Field(fldPath[1:]) - case utils.MetaOpts: - val, err = ar.Opts.Field(fldPath[1:]) + if nmItems, isNMItems := val.([]*utils.DataNode); isNMItems { // special handling of NMItems, take the last value out of it + el := nmItems[len(nmItems)-1] + if el.Type == utils.NMDataType { + val = el.Value.Data + } } return } @@ -184,7 +160,7 @@ func (ar *AgentRequest) FieldAsString(fldPath []string) (val string, err error) //SetFields will populate fields of AgentRequest out of templates func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { - ar.tmp = utils.NavigableMap{} + ar.tmp = &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} for _, tplFld := range tplFlds { if pass, err := ar.filterS.Pass(ar.Tenant, tplFld.Filters, ar); err != nil { @@ -224,22 +200,22 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { return } else if fullPath == nil { // no dynamic path fullPath = &utils.FullPath{ - PathItems: tplFld.GetPathItems().Clone(), // need to clone so me do not modify the template + PathItems: utils.CloneSlice(tplFld.GetPathItems()), // need to clone so me do not modify the template Path: tplFld.Path, } itmPath = tplFld.GetPathSlice()[1:] } else { - itmPath = fullPath.PathItems.Slice()[1:] + itmPath = fullPath.PathItems[1:] } - nMItm := &config.NMItem{Data: out, Path: itmPath, Config: tplFld} + nMItm := &utils.DataLeaf{Data: out, Path: itmPath, NewBranch: tplFld.NewBranch, AttributeID: tplFld.AttributeID} switch tplFld.Type { case utils.MetaComposed: - err = utils.ComposeNavMapVal(ar, fullPath, nMItm) + err = ar.Compose(fullPath, nMItm) case utils.MetaGroup: // in case of *group type simply append to valSet - err = utils.AppendNavMapVal(ar, fullPath, nMItm) + err = ar.Append(fullPath, nMItm) default: - _, err = ar.Set(fullPath, &utils.NMSlice{nMItm}) + err = ar.SetAsSlice(fullPath, nMItm) } if err != nil { return @@ -253,40 +229,39 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { } // Set implements utils.NMInterface -func (ar *AgentRequest) Set(fullPath *utils.FullPath, nm utils.NMInterface) (added bool, err error) { - switch fullPath.PathItems[0].Field { +func (ar *AgentRequest) SetAsSlice(fullPath *utils.FullPath, nm *utils.DataLeaf) (err error) { + switch fullPath.PathItems[0] { default: - return false, fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0].Field) + return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0]) case utils.MetaVars: - return ar.Vars.Set(fullPath.PathItems[1:], nm) + _, err = ar.Vars.Set(fullPath.PathItems[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) + return case utils.MetaCgreq: - return ar.CGRRequest.Set(&utils.FullPath{ + return ar.CGRRequest.SetAsSlice(&utils.FullPath{ PathItems: fullPath.PathItems[1:], Path: fullPath.Path[7:], - }, nm) + }, []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) case utils.MetaCgrep: - return ar.CGRReply.Set(fullPath.PathItems[1:], nm) + _, err = ar.CGRReply.Set(fullPath.PathItems[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) + return case utils.MetaRep: - return ar.Reply.Set(&utils.FullPath{ + return ar.Reply.SetAsSlice(&utils.FullPath{ PathItems: fullPath.PathItems[1:], Path: fullPath.Path[5:], - }, nm) + }, []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) case utils.MetaDiamreq: - return ar.diamreq.Set(&utils.FullPath{ + return ar.diamreq.SetAsSlice(&utils.FullPath{ PathItems: fullPath.PathItems[1:], Path: fullPath.Path[9:], - }, nm) + }, []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) case utils.MetaTmp: - return ar.tmp.Set(fullPath.PathItems[1:], nm) + _, err = ar.tmp.Set(fullPath.PathItems[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) + return case utils.MetaOpts: - return ar.Opts.Set(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], - Path: fullPath.Path[6:], - }, nm) + return ar.Opts.Set(fullPath.PathItems[1:], nm.Data) case utils.MetaUCH: - err = engine.Cache.Set(utils.CacheUCH, fullPath.Path[5:], nm, nil, true, utils.NonTransactional) + return engine.Cache.Set(utils.CacheUCH, fullPath.Path[5:], nm.Data, nil, true, utils.NonTransactional) } - return false, err } // RemoveAll deletes all fields at given prefix @@ -295,56 +270,53 @@ func (ar *AgentRequest) RemoveAll(prefix string) error { default: return fmt.Errorf("unsupported field prefix: <%s> when set fields", prefix) case utils.MetaVars: - ar.Vars = utils.NavigableMap{} + ar.Vars = &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} case utils.MetaCgreq: ar.CGRRequest.RemoveAll() case utils.MetaCgrep: - ar.CGRReply = &utils.NavigableMap{} + ar.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} case utils.MetaRep: ar.Reply.RemoveAll() case utils.MetaDiamreq: ar.diamreq.RemoveAll() case utils.MetaTmp: - ar.tmp = utils.NavigableMap{} + ar.tmp = &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} case utils.MetaUCH: engine.Cache.Clear([]string{utils.CacheUCH}) case utils.MetaOpts: - ar.Opts.RemoveAll() + ar.Opts = make(utils.MapStorage) } return nil } // Remove deletes the fields found at path with the given prefix func (ar *AgentRequest) Remove(fullPath *utils.FullPath) error { - switch fullPath.PathItems[0].Field { + switch fullPath.PathItems[0] { default: - return fmt.Errorf("unsupported field prefix: <%s> when set fields", fullPath.PathItems[0].Field) + return fmt.Errorf("unsupported field prefix: <%s> when set fields", fullPath.PathItems[0]) case utils.MetaVars: - return ar.Vars.Remove(fullPath.PathItems[1:]) + return ar.Vars.Remove(utils.CloneSlice(fullPath.PathItems[1:])) case utils.MetaCgreq: return ar.CGRRequest.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:].Clone(), + PathItems: fullPath.PathItems[1:], Path: fullPath.Path[7:], }) case utils.MetaCgrep: - return ar.CGRReply.Remove(fullPath.PathItems[1:]) + return ar.CGRReply.Remove(utils.CloneSlice(fullPath.PathItems[1:])) case utils.MetaRep: return ar.Reply.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:].Clone(), + PathItems: fullPath.PathItems[1:], Path: fullPath.Path[5:], }) case utils.MetaDiamreq: return ar.diamreq.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:].Clone(), + PathItems: fullPath.PathItems[1:], Path: fullPath.Path[9:], }) case utils.MetaTmp: - return ar.tmp.Remove(fullPath.PathItems[1:]) + return ar.tmp.Remove(utils.CloneSlice(fullPath.PathItems[1:])) case utils.MetaOpts: - return ar.Opts.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:].Clone(), - Path: fullPath.Path[6:], - }) + return ar.Opts.Remove(fullPath.PathItems[1:]) case utils.MetaUCH: return engine.Cache.Remove(utils.CacheUCH, fullPath.Path[5:], true, utils.NonTransactional) } @@ -508,29 +480,111 @@ func (ar *AgentRequest) ParseField( // setCGRReply will set the aReq.cgrReply based on reply coming from upstream or error // returns error in case of reply not converting to NavigableMap -func (ar *AgentRequest) setCGRReply(rply utils.NavigableMapper, errRply error) (err error) { - var nm utils.NavigableMap - if errRply != nil { - nm = utils.NavigableMap{utils.Error: utils.NewNMData(errRply.Error())} - } else { - nm = utils.NavigableMap{} - if rply != nil { - nm = rply.AsNavigableMap() - } - nm.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData("")) // enforce empty error +func (ar *AgentRequest) setCGRReply(rply utils.NavigableMapper, err error) { + ar.CGRReply = &utils.DataNode{ + Type: utils.NMMapType, + Map: make(map[string]*utils.DataNode), } - *ar.CGRReply = nm // update value so we can share CGRReply - return + var errMsg string + if err != nil { + errMsg = err.Error() + } else if rply != nil { + ar.CGRReply.Map = rply.AsNavigableMap() + } + ar.CGRReply.Map[utils.Error] = utils.NewLeafNode(errMsg) } func needsMaxUsage(ralsFlags utils.FlagParams) bool { - if len(ralsFlags) == 0 { - return false - } - for _, flag := range []string{utils.MetaAuthorize, utils.MetaInitiate, utils.MetaUpdate} { - if ralsFlags.Has(flag) { - return true - } - } - return false + return len(ralsFlags) != 0 && + (ralsFlags.Has(utils.MetaAuthorize) || + ralsFlags.Has(utils.MetaInitiate) || + ralsFlags.Has(utils.MetaUpdate)) +} + +// Set sets the value at the given path +// this used with full path and the processed path to not calculate them for every set +func (ar *AgentRequest) Append(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { + switch fullPath.PathItems[0] { + default: + return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0]) + case utils.MetaVars: + _, err = ar.Vars.Append(fullPath.PathItems[1:], val) + return + case utils.MetaCgreq: + return ar.CGRRequest.Append(&utils.FullPath{ + PathItems: fullPath.PathItems[1:], + Path: fullPath.Path[7:], + }, val) + case utils.MetaCgrep: + _, err = ar.CGRReply.Append(fullPath.PathItems[1:], val) + return + case utils.MetaRep: + return ar.Reply.Append(&utils.FullPath{ + PathItems: fullPath.PathItems[1:], + Path: fullPath.Path[5:], + }, val) + case utils.MetaDiamreq: + return ar.diamreq.Append(&utils.FullPath{ + PathItems: fullPath.PathItems[1:], + Path: fullPath.Path[9:], + }, val) + case utils.MetaTmp: + _, err = ar.tmp.Append(fullPath.PathItems[1:], val) + return + case utils.MetaOpts: + return ar.Opts.Set(fullPath.PathItems[1:], val.Data) + case utils.MetaUCH: + return engine.Cache.Set(utils.CacheUCH, fullPath.Path[5:], val.Data, nil, true, utils.NonTransactional) + } +} + +// Set sets the value at the given path +// this used with full path and the processed path to not calculate them for every set +func (ar *AgentRequest) Compose(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { + switch fullPath.PathItems[0] { + default: + return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0]) + case utils.MetaVars: + return ar.Vars.Compose(fullPath.PathItems[1:], val) + case utils.MetaCgreq: + return ar.CGRRequest.Compose(&utils.FullPath{ + PathItems: fullPath.PathItems[1:], + Path: fullPath.Path[7:], + }, val) + case utils.MetaCgrep: + return ar.CGRReply.Compose(fullPath.PathItems[1:], val) + case utils.MetaRep: + return ar.Reply.Compose(&utils.FullPath{ + PathItems: fullPath.PathItems[1:], + Path: fullPath.Path[5:], + }, val) + case utils.MetaDiamreq: + return ar.diamreq.Compose(&utils.FullPath{ + PathItems: fullPath.PathItems[1:], + Path: fullPath.Path[9:], + }, val) + case utils.MetaTmp: + return ar.tmp.Compose(fullPath.PathItems[1:], val) + case utils.MetaOpts: + var prv interface{} + if prv, err = ar.Opts.FieldAsInterface(fullPath.PathItems[1:]); err != nil { + if err != utils.ErrNotFound { + return + } + prv = val.Data + } else { + prv = utils.IfaceAsString(prv) + utils.IfaceAsString(val.Data) + } + return ar.Opts.Set(fullPath.PathItems[1:], prv) + + case utils.MetaUCH: + path := fullPath.Path[5:] + var prv interface{} + if prvI, ok := engine.Cache.Get(utils.CacheUCH, path); !ok { + prv = val.Data + } else { + prv = utils.IfaceAsString(prvI) + utils.IfaceAsString(val.Data) + } + return engine.Cache.Set(utils.CacheUCH, path, prv, nil, true, utils.NonTransactional) + } } diff --git a/agents/agentreq_test.go b/agents/agentreq_test.go index c465ed772..43363ce67 100644 --- a/agents/agentreq_test.go +++ b/agents/agentreq_test.go @@ -44,24 +44,25 @@ func TestAgReqSetFields(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: utils.PathItems{{Field: utils.CGRID}}}, utils.NewNMData( - utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( - time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: utils.PathItems{{Field: utils.Usage}}}, utils.NewNMData(3*time.Minute)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: []string{utils.CGRID}}, + utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.MetaVoice) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, "1001") + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, "1002") + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, + time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.MetaPrepaid) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: []string{utils.Usage}}, 3*time.Minute) - cgrRply := utils.NavigableMap{ - utils.CapAttributes: utils.NavigableMap{ - "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), - }, - utils.CapMaxUsage: utils.NewNMData(120 * time.Second), - utils.Error: utils.NewNMData(""), + cgrRply := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.CapAttributes: {Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + "PaypalAccount": utils.NewLeafNode("cgrates@paypal.com"), + }}, + utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), + utils.Error: utils.NewLeafNode(""), + }, } - agReq.CGRReply = &cgrRply + agReq.CGRReply = cgrRply tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -111,28 +112,24 @@ func TestAgReqSetFields(t *testing.T) { } eMp := utils.NewOrderedNavigableMap() - eMp.Set(&utils.FullPath{Path: utils.Tenant, PathItems: utils.PathItems{{Field: utils.Tenant}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) - eMp.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}) - eMp.Set(&utils.FullPath{Path: "RequestedUsage", PathItems: utils.PathItems{{Field: "RequestedUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "180", Path: []string{"RequestedUsage"}, - Config: tplFlds[3]}}) - eMp.Set(&utils.FullPath{Path: "PaypalAccount", PathItems: utils.PathItems{{Field: "PaypalAccount"}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}, - Config: tplFlds[6]}}) - eMp.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[7]}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Tenant, PathItems: []string{utils.Tenant}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathItems: []string{"RequestedUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180", Path: []string{"RequestedUsage"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathItems: []string{"PaypalAccount"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.Reply, eMp) { + t.Log(utils.ToJSON(eMp.GetOrder())) + t.Log(utils.ToJSON(agReq.Reply.GetOrder())) t.Errorf("expecting: %+v,\n received: %+v", eMp, agReq.Reply) } } @@ -176,14 +173,14 @@ func TestAgentRequestSetFields(t *testing.T) { if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"Account"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { - t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if nm, ok := val.([]*utils.DataNode); !ok { + t.Errorf("Expecting NM items<%T>", val) + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } // case utils.MetaCgreq @@ -198,14 +195,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.CGRRequest.Field(utils.PathItems{{Field: "Account"}}); err != nil { + } else if val, err := ar.CGRRequest.FieldAsInterface([]string{"Account"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } // case utils.MetaCgrep @@ -220,14 +217,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.CGRReply.Field(utils.PathItems{{Field: "Account"}}); err != nil { + } else if val, err := ar.CGRReply.FieldAsInterface([]string{"Account"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } // case utils.MetaRep @@ -242,14 +239,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Reply.Field(utils.PathItems{{Field: "Account"}}); err != nil { + } else if val, err := ar.Reply.FieldAsInterface([]string{"Account"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } // case utils.MetaDiamreq @@ -264,14 +261,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.diamreq.Field(utils.PathItems{{Field: "Account"}}); err != nil { + } else if val, err := ar.diamreq.FieldAsInterface([]string{"Account"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } //MetaComposed @@ -301,14 +298,14 @@ func TestAgentRequestSetFields(t *testing.T) { if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "AccountID"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"AccountID"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "cgrates.org:1009" { - t.Error("Expecting 'cgrates.org:1009', received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "cgrates.org:1009" { + t.Error("Expecting 'cgrates.org:1009', received: ", nm[0].Value.Data) } // MetaConstant @@ -323,14 +320,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"Account"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "2020" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "2020" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } // Filters @@ -346,14 +343,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "AccountID"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"AccountID"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item ", utils.ToJSON(nm)) - } else if (*nm)[0].Interface() != "cgrates.org:1009" { - t.Error("Expecting 'cgrates.org:1009', received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "cgrates.org:1009" { + t.Error("Expecting 'cgrates.org:1009', received: ", nm[0].Value.Data) } input = []*config.FCTemplate{ @@ -391,14 +388,14 @@ func TestAgentRequestSetFields(t *testing.T) { } if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Name"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"Name"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } // ErrNotFound @@ -413,7 +410,7 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if _, err := ar.Vars.Field(utils.PathItems{{Field: "Test"}}); err == nil || err != utils.ErrNotFound { + } else if _, err := ar.Vars.FieldAsInterface([]string{"Test"}); err == nil || err != utils.ErrNotFound { t.Errorf("Expecting: %+v, received: %+v", utils.ErrNotFound, err) } input = []*config.FCTemplate{ @@ -457,14 +454,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account4"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"Account4"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } input = []*config.FCTemplate{ @@ -478,14 +475,14 @@ func TestAgentRequestSetFields(t *testing.T) { input[0].ComputePath() if err := ar.SetFields(input); err != nil { t.Error(err) - } else if val, err := ar.Vars.Field(utils.PathItems{{Field: "Account5"}}); err != nil { + } else if val, err := ar.Vars.FieldAsInterface([]string{"Account5"}); err != nil { t.Error(err) - } else if nm, ok := val.(*utils.NMSlice); !ok { + } else if nm, ok := val.([]*utils.DataNode); !ok { t.Error("Expecting NM items") - } else if len(*nm) != 1 { + } else if len(nm) != 1 { t.Error("Expecting one item") - } else if (*nm)[0].Interface() != "1009" { - t.Error("Expecting 1009, received: ", (*nm)[0].Interface()) + } else if nm[0].Value.Data != "1009" { + t.Error("Expecting 1009, received: ", nm[0].Value.Data) } } @@ -496,12 +493,11 @@ func TestAgReqMaxCost(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CapMaxUsage, PathItems: utils.PathItems{{Field: utils.CapMaxUsage}}}, utils.NewNMData("120s")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CapMaxUsage, PathItems: []string{utils.CapMaxUsage}}, utils.NewLeafNode("120s")) - cgrRply := utils.NavigableMap{ - utils.CapMaxUsage: utils.NewNMData(120 * time.Second), - } - agReq.CGRReply = &cgrRply + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), + }} tplFlds := []*config.FCTemplate{ {Tag: "MaxUsage", @@ -513,13 +509,14 @@ func TestAgReqMaxCost(t *testing.T) { tplFlds[0].ComputePath() eMp := utils.NewOrderedNavigableMap() - eMp.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[0]}}) + eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.Reply, eMp) { + t.Log(utils.ToJSON(eMp.GetOrder())) + t.Log(utils.ToJSON(agReq.Reply.GetOrder())) t.Errorf("expecting: %+v,\n received: %+v", eMp, agReq.Reply) } } @@ -739,10 +736,10 @@ func TestAgReqEmptyFilter(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: utils.PathItems{{Field: utils.CGRID}}}, utils.NewNMData( - utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: []string{utils.CGRID}}, + utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", Filters: []string{}, @@ -759,16 +756,13 @@ func TestAgReqEmptyFilter(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) - eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + eMp.Set([]string{utils.Destination}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -783,8 +777,8 @@ func TestAgReqMetaExponent(t *testing.T) { config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Value", PathItems: utils.PathItems{{Field: "Value"}}}, utils.NewNMData("2")) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Exponent", PathItems: utils.PathItems{{Field: "Exponent"}}}, utils.NewNMData("2")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Value", PathItems: []string{"Value"}}, utils.NewLeafNode("2")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Exponent", PathItems: []string{"Exponent"}}, utils.NewLeafNode("2")) tplFlds := []*config.FCTemplate{ {Tag: "TestExpo", Filters: []string{}, @@ -792,10 +786,9 @@ func TestAgReqMetaExponent(t *testing.T) { Value: config.NewRSRParsersMustCompile("~*cgreq.Value;~*cgreq.Exponent", utils.InfieldSep)}, } tplFlds[0].ComputePath() - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: "TestExpo"}}, &utils.NMSlice{ - &config.NMItem{Data: "200", Path: []string{"TestExpo"}, - Config: tplFlds[0]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{"TestExpo"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "200", Path: []string{"TestExpo"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -811,9 +804,9 @@ func TestAgReqFieldAsNone(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -830,13 +823,11 @@ func TestAgReqFieldAsNone(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { @@ -851,9 +842,9 @@ func TestAgReqFieldAsNone2(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -870,16 +861,13 @@ func TestAgReqFieldAsNone2(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) - eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[3]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + eMp.Set([]string{utils.Destination}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { @@ -894,14 +882,14 @@ func TestAgReqSetField2(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) - agReq.CGRReply = &utils.NavigableMap{} + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -924,22 +912,17 @@ func TestAgReqSetField2(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) - eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}) - eMp.Set(utils.PathItems{{Field: "Usage"}}, &utils.NMSlice{ - &config.NMItem{Data: "30s", Path: []string{"Usage"}, - Config: tplFlds[3]}}) - eMp.Set(utils.PathItems{{Field: "CalculatedUsage"}}, &utils.NMSlice{ - &config.NMItem{Data: time.Date(2013, 12, 30, 14, 59, 31, 0, time.UTC), Path: []string{"CalculatedUsage"}, - Config: tplFlds[4]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + eMp.Set([]string{utils.Destination}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + eMp.Set([]string{"Usage"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "30s", Path: []string{"Usage"}}}}) + eMp.Set([]string{"CalculatedUsage"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: time.Date(2013, 12, 30, 14, 59, 31, 0, time.UTC), Path: []string{"CalculatedUsage"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -956,10 +939,10 @@ func TestAgReqFieldAsInterface(t *testing.T) { agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent agReq.CGRRequest = utils.NewOrderedNavigableMap() - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: utils.PathItems{{Field: utils.Usage}}}, &utils.NMSlice{&config.NMItem{Data: 3 * time.Minute}}) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, &utils.NMSlice{&config.NMItem{Data: utils.MetaVoice}}) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: []string{utils.Usage}}, &utils.DataNode{Type: utils.NMSliceType, Slice: []*utils.DataNode{{Type: utils.NMDataType, Value: &utils.DataLeaf{Data: 3 * time.Minute}}}}) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, &utils.DataNode{Type: utils.NMSliceType, Slice: []*utils.DataNode{{Type: utils.NMDataType, Value: &utils.DataLeaf{Data: utils.MetaVoice}}}}) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) path := []string{utils.MetaCgreq, utils.Usage} var expVal interface{} @@ -1003,19 +986,15 @@ func TestAgReqNewARWithCGRRplyAndRply(t *testing.T) { rply := utils.NewOrderedNavigableMap() rply.Set(&utils.FullPath{ - Path: "FirstLevel.SecondLevel.Fld1", - PathItems: utils.PathItems{ - {Field: "FirstLevel"}, - {Field: "SecondLevel"}, - {Field: "Fld1"}, - }}, utils.NewNMData("Val1")) - cgrRply := &utils.NavigableMap{ - utils.CapAttributes: utils.NavigableMap{ - "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), - }, - utils.CapMaxUsage: utils.NewNMData(120 * time.Second), - utils.Error: utils.NewNMData(""), - } + Path: "FirstLevel.SecondLevel.Fld1", + PathItems: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) + cgrRply := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.CapAttributes: &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + "PaypalAccount": utils.NewLeafNode("cgrates@paypal.com"), + }}, + utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), + utils.Error: utils.NewLeafNode(""), + }} agReq := NewAgentRequest(nil, nil, cgrRply, rply, nil, nil, "cgrates.org", "", filterS, nil, nil) @@ -1032,12 +1011,10 @@ func TestAgReqNewARWithCGRRplyAndRply(t *testing.T) { } eMp := utils.NewOrderedNavigableMap() - eMp.Set(&utils.FullPath{Path: "Fld1", PathItems: utils.PathItems{{Field: "Fld1"}}}, &utils.NMSlice{ - &config.NMItem{Data: "Val1", Path: []string{"Fld1"}, - Config: tplFlds[0]}}) - eMp.Set(&utils.FullPath{Path: "Fld2", PathItems: utils.PathItems{{Field: "Fld2"}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"Fld2"}, - Config: tplFlds[1]}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld1", PathItems: []string{"Fld1"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "Val1", Path: []string{"Fld1"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld2", PathItems: []string{"Fld2"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"Fld2"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1054,12 +1031,8 @@ func TestAgReqSetCGRReplyWithError(t *testing.T) { rply := utils.NewOrderedNavigableMap() rply.Set(&utils.FullPath{ - Path: "FirstLevel.SecondLevel.Fld1", - PathItems: utils.PathItems{ - {Field: "FirstLevel"}, - {Field: "SecondLevel"}, - {Field: "Fld1"}, - }}, utils.NewNMData("Val1")) + Path: "FirstLevel.SecondLevel.Fld1", + PathItems: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) agReq := NewAgentRequest(nil, nil, nil, rply, nil, nil, "cgrates.org", "", filterS, nil, nil) agReq.setCGRReply(nil, utils.ErrNotFound) @@ -1082,10 +1055,10 @@ func TestAgReqSetCGRReplyWithError(t *testing.T) { } } -type myEv map[string]utils.NMInterface +type myEv map[string]*utils.DataNode -func (ev myEv) AsNavigableMap() utils.NavigableMap { - return utils.NavigableMap(ev) +func (ev myEv) AsNavigableMap() map[string]*utils.DataNode { + return ev } func TestAgReqSetCGRReplyWithoutError(t *testing.T) { @@ -1096,19 +1069,15 @@ func TestAgReqSetCGRReplyWithoutError(t *testing.T) { rply := utils.NewOrderedNavigableMap() rply.Set(&utils.FullPath{ - Path: "FirstLevel.SecondLevel.Fld1", - PathItems: utils.PathItems{ - {Field: "FirstLevel"}, - {Field: "SecondLevel"}, - {Field: "Fld1"}, - }}, utils.NewNMData("Val1")) + Path: "FirstLevel.SecondLevel.Fld1", + PathItems: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) myEv := myEv{ - utils.CapAttributes: utils.NavigableMap{ - "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), - }, - utils.CapMaxUsage: utils.NewNMData(120 * time.Second), - utils.Error: utils.NewNMData(""), + utils.CapAttributes: &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + "PaypalAccount": utils.NewLeafNode("cgrates@paypal.com"), + }}, + utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), + utils.Error: utils.NewLeafNode(""), } agReq := NewAgentRequest(nil, nil, nil, rply, nil, @@ -1128,16 +1097,16 @@ func TestAgReqSetCGRReplyWithoutError(t *testing.T) { v.ComputePath() } eMp := utils.NewOrderedNavigableMap() - eMp.Set(&utils.FullPath{Path: "Fld1", PathItems: utils.PathItems{{Field: "Fld1"}}}, &utils.NMSlice{ - &config.NMItem{Data: "Val1", Path: []string{"Fld1"}, - Config: tplFlds[0]}}) - eMp.Set(&utils.FullPath{Path: "Fld2", PathItems: utils.PathItems{{Field: "Fld2"}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"Fld2"}, - Config: tplFlds[1]}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld1", PathItems: []string{"Fld1"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "Val1", Path: []string{"Fld1"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld2", PathItems: []string{"Fld2"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"Fld2"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRRequest, eMp) { + t.Log(utils.ToJSON(eMp.GetOrder())) + t.Log(utils.ToJSON(agReq.CGRRequest.GetOrder())) t.Errorf("expecting: %+v,\n received: %+v", eMp, agReq.CGRRequest) } } @@ -1540,14 +1509,14 @@ func TestAgReqOverwrite(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) - agReq.CGRReply = &utils.NavigableMap{} + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} tplFlds := []*config.FCTemplate{ {Tag: "Account", @@ -1573,15 +1542,15 @@ func TestAgReqOverwrite(t *testing.T) { t.Error(err) } - if rcv, err := agReq.CGRReply.Field(utils.PathItems{{Field: utils.AccountField}}); err != nil { + if rcv, err := agReq.CGRReply.FieldAsInterface([]string{utils.AccountField}); err != nil { t.Error(err) - } else if sls, canCast := rcv.(*utils.NMSlice); !canCast { + } else if sls, canCast := rcv.([]*utils.DataNode); !canCast { t.Errorf("Cannot cast to &utils.NMSlice %+v", rcv) - } else if len(*sls) != 1 { - t.Errorf("expecting: %+v, \n received: %+v ", 1, len(*sls)) - } else if (*sls)[0].Interface() != "OverwrittenAccountWithComposed" { + } else if len(sls) != 1 { + t.Errorf("expecting: %+v, \n received: %+v ", 1, len(sls)) + } else if (sls)[0].Value.Data != "OverwrittenAccountWithComposed" { t.Errorf("expecting: %+v, \n received: %+v ", - "OverwrittenAccountWithComposed", (*sls)[0].Interface()) + "OverwrittenAccountWithComposed", (sls)[0].Value.Data) } } @@ -1592,14 +1561,14 @@ func TestAgReqGroupType(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) - agReq.CGRReply = &utils.NavigableMap{} + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} tplFlds := []*config.FCTemplate{ {Tag: "Account", @@ -1616,16 +1585,16 @@ func TestAgReqGroupType(t *testing.T) { t.Error(err) } - if rcv, err := agReq.CGRReply.Field(utils.PathItems{{Field: utils.AccountField}}); err != nil { + if rcv, err := agReq.CGRReply.FieldAsInterface([]string{utils.AccountField}); err != nil { t.Error(err) - } else if sls, canCast := rcv.(*utils.NMSlice); !canCast { + } else if sls, canCast := rcv.([]*utils.DataNode); !canCast { t.Errorf("Cannot cast to &utils.NMSlice %+v", rcv) - } else if len(*sls) != 2 { - t.Errorf("expecting: %+v, \n received: %+v ", 1, len(*sls)) - } else if (*sls)[0].Interface() != "cgrates.org" { - t.Errorf("expecting: %+v, \n received: %+v ", "cgrates.org", (*sls)[0].Interface()) - } else if (*sls)[1].Interface() != "test" { - t.Errorf("expecting: %+v, \n received: %+v ", "test", (*sls)[1].Interface()) + } else if len(sls) != 2 { + t.Errorf("expecting: %+v, \n received: %+v ", 1, len(sls)) + } else if (sls)[0].Value.Data != "cgrates.org" { + t.Errorf("expecting: %+v, \n received: %+v ", "cgrates.org", (sls)[0].Value.Data) + } else if (sls)[1].Value.Data != "test" { + t.Errorf("expecting: %+v, \n received: %+v ", "test", (sls)[1].Value.Data) } } @@ -1635,7 +1604,7 @@ func TestAgReqSetFieldsInTmp(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -1648,13 +1617,11 @@ func TestAgReqSetFieldsInTmp(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1669,7 +1636,7 @@ func TestAgReqSetFieldsIp2Hex(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: "IP", PathItems: utils.PathItems{{Field: "IP"}}}, utils.NewNMData("62.87.114.244")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "IP", PathItems: []string{"IP"}}, utils.NewLeafNode("62.87.114.244")) tplFlds := []*config.FCTemplate{ {Tag: "IP", @@ -1679,10 +1646,9 @@ func TestAgReqSetFieldsIp2Hex(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: "IP"}}, &utils.NMSlice{ - &config.NMItem{Data: "0x3e5772f4", Path: []string{"IP"}, - Config: tplFlds[0]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{"IP"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "0x3e5772f4", Path: []string{"IP"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1697,7 +1663,7 @@ func TestAgReqSetFieldsString2Hex(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: "CustomField", PathItems: utils.PathItems{{Field: "CustomField"}}}, utils.NewNMData(string([]byte{0x94, 0x71, 0x02, 0x31, 0x01, 0x59}))) + agReq.CGRRequest.Set(&utils.FullPath{Path: "CustomField", PathItems: []string{"CustomField"}}, utils.NewLeafNode(string([]byte{0x94, 0x71, 0x02, 0x31, 0x01, 0x59}))) tplFlds := []*config.FCTemplate{ {Tag: "CustomField", @@ -1707,10 +1673,9 @@ func TestAgReqSetFieldsString2Hex(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: "CustomField"}}, &utils.NMSlice{ - &config.NMItem{Data: "0x947102310159", Path: []string{"CustomField"}, - Config: tplFlds[0]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{"CustomField"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "0x947102310159", Path: []string{"CustomField"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1726,23 +1691,23 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: utils.PathItems{{Field: utils.CGRID}}}, utils.NewNMData( - utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: []string{utils.CGRID}}, + utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: utils.PathItems{{Field: utils.Usage}}}, utils.NewNMData(3*time.Minute)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: []string{utils.Usage}}, utils.NewLeafNode(3*time.Minute)) - agReq.CGRReply = &utils.NavigableMap{ - utils.CapAttributes: utils.NavigableMap{ - "PaypalAccount": utils.NewNMData("cgrates@paypal.com"), - }, - utils.CapMaxUsage: utils.NewNMData(120 * time.Second), - utils.Error: utils.NewNMData(""), - } + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.CapAttributes: &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + "PaypalAccount": utils.NewLeafNode("cgrates@paypal.com"), + }}, + utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), + utils.Error: utils.NewLeafNode(""), + }} tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -1791,24 +1756,18 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { v.ComputePath() } eMp := utils.NewOrderedNavigableMap() - eMp.Set(&utils.FullPath{Path: utils.Tenant, PathItems: utils.PathItems{{Field: utils.Tenant}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) - eMp.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}) - eMp.Set(&utils.FullPath{Path: "RequestedUsage", PathItems: utils.PathItems{{Field: "RequestedUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "180", Path: []string{"RequestedUsage"}, - Config: tplFlds[3]}}) - eMp.Set(&utils.FullPath{Path: "PaypalAccount", PathItems: utils.PathItems{{Field: "PaypalAccount"}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}, - Config: tplFlds[6]}}) - eMp.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[7]}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Tenant, PathItems: []string{utils.Tenant}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathItems: []string{"RequestedUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180", Path: []string{"RequestedUsage"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathItems: []string{"PaypalAccount"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1826,18 +1785,14 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { v.ComputePath() } eMpRemove := utils.NewOrderedNavigableMap() - eMpRemove.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}) - eMpRemove.Set(&utils.FullPath{Path: "RequestedUsage", PathItems: utils.PathItems{{Field: "RequestedUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "180", Path: []string{"RequestedUsage"}, - Config: tplFlds[3]}}) - eMpRemove.Set(&utils.FullPath{Path: "PaypalAccount", PathItems: utils.PathItems{{Field: "PaypalAccount"}}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}, - Config: tplFlds[6]}}) - eMpRemove.Set(&utils.FullPath{Path: "MaxUsage", PathItems: utils.PathItems{{Field: "MaxUsage"}}}, &utils.NMSlice{ - &config.NMItem{Data: "120", Path: []string{"MaxUsage"}, - Config: tplFlds[7]}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathItems: []string{"RequestedUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180", Path: []string{"RequestedUsage"}}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathItems: []string{"PaypalAccount"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) if err := agReq.SetFields(tplFldsRemove); err != nil { t.Error(err) @@ -1864,7 +1819,7 @@ func TestAgReqSetFieldsInCache(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) engine.NewCacheS(cfg, dm, nil) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -1907,7 +1862,7 @@ func TestAgReqSetFieldsInCacheWithTimeOut(t *testing.T) { cfg.CacheCfg().Partitions[utils.CacheUCH].TTL = time.Second engine.Cache = engine.NewCacheS(cfg, dm, nil) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -2031,17 +1986,17 @@ func TestAgReqDynamicPath(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE1", PathItems: utils.PathItems{{Field: "Routes"}, {Field: "CGR_ROUTE1"}}}, utils.NewNMData(1001)) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE2", PathItems: utils.PathItems{{Field: "Routes"}, {Field: "CGR_ROUTE2"}}}, utils.NewNMData(1002)) - agReq.CGRRequest.Set(&utils.FullPath{Path: "BestRoute", PathItems: utils.PathItems{{Field: "BestRoute"}}}, utils.NewNMData("ROUTE1")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE1", PathItems: []string{"Routes", "CGR_ROUTE1"}}, utils.NewLeafNode(1001)) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE2", PathItems: []string{"Routes", "CGR_ROUTE2"}}, utils.NewLeafNode(1002)) + agReq.CGRRequest.Set(&utils.FullPath{Path: "BestRoute", PathItems: []string{"BestRoute"}}, utils.NewLeafNode("ROUTE1")) - agReq.CGRReply = &utils.NavigableMap{} + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} val1, err := config.NewRSRParsersFromSlice([]string{"~*cgreq.Routes."}) if err != nil { t.Error(err) @@ -2071,30 +2026,24 @@ func TestAgReqDynamicPath(t *testing.T) { for _, v := range tplFlds { v.ComputePath() } - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField}, - Config: tplFlds[1]}}) - eMp.Set(utils.PathItems{{Field: utils.Destination}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{utils.Destination}, - Config: tplFlds[2]}}) - eMp.Set(utils.PathItems{{Field: "Usage"}}, &utils.NMSlice{ - &config.NMItem{Data: "30s", Path: []string{"Usage"}, - Config: tplFlds[3]}}) - eMp.Set(utils.PathItems{{Field: "Route"}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{"Route"}, - Config: tplFlds[4]}}) - eMp.Set(utils.PathItems{{Field: "Route2"}, {Field: "CGR_ROUTE1"}}, &utils.NMSlice{ - &config.NMItem{Data: "1002", Path: []string{"Route2", "CGR_ROUTE1"}, - Config: tplFlds[5]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + eMp.Set([]string{utils.Destination}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + eMp.Set([]string{"Usage"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "30s", Path: []string{"Usage"}}}}) + eMp.Set([]string{"Route"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{"Route"}}}}) + eMp.Set([]string{"Route2", "CGR_ROUTE1"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{"Route2", "CGR_ROUTE1"}}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { - t.Errorf("expecting: %+v,\n received: %+v", eMp, agReq.CGRReply) + t.Errorf("expecting: %+v,\n received: %+v", utils.ToJSON(eMp), utils.ToJSON(agReq.CGRReply)) } } @@ -2105,15 +2054,15 @@ func TestAgReqRoundingDecimals(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Cost, PathItems: utils.PathItems{{Field: utils.Cost}}}, utils.NewNMData(12.12645)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Cost, PathItems: []string{utils.Cost}}, utils.NewLeafNode(12.12645)) - agReq.CGRReply = &utils.NavigableMap{} + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} tplFlds := []*config.FCTemplate{ {Tag: "Cost", @@ -2127,15 +2076,15 @@ func TestAgReqRoundingDecimals(t *testing.T) { t.Error(err) } - if rcv, err := agReq.CGRReply.Field(utils.PathItems{{Field: utils.Cost}}); err != nil { + if rcv, err := agReq.CGRReply.FieldAsInterface([]string{utils.Cost}); err != nil { t.Error(err) - } else if sls, canCast := rcv.(*utils.NMSlice); !canCast { + } else if sls, canCast := rcv.([]*utils.DataNode); !canCast { t.Errorf("Cannot cast to &utils.NMSlice %+v", rcv) - } else if len(*sls) != 1 { - t.Errorf("expecting: %+v, \n received: %+v ", 1, len(*sls)) - } else if (*sls)[0].Interface() != "12.126" { + } else if len(sls) != 1 { + t.Errorf("expecting: %+v, \n received: %+v ", 1, len(sls)) + } else if (sls)[0].Value.Data != "12.126" { t.Errorf("expecting: %+v, \n received: %+v", - "12.126", (*sls)[0].Interface()) + "12.126", (sls)[0].Value.Data) } } @@ -2169,28 +2118,25 @@ func BenchmarkAgReqSetField(b *testing.B) { for _, v := range tplFlds { v.ComputePath() } - eMp := &utils.NavigableMap{} - eMp.Set(utils.PathItems{{Field: utils.Tenant}}, &utils.NMSlice{ - &config.NMItem{Data: "cgrates.org", Path: []string{utils.Tenant}, - Config: tplFlds[0]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField, Index: []string{"0"}}, {Field: "ID"}}, &utils.NMSlice{ - &config.NMItem{Data: "1001", Path: []string{utils.AccountField + "[0]", "ID"}, - Config: tplFlds[1]}}) - eMp.Set(utils.PathItems{{Field: utils.AccountField, Index: []string{"1"}}, {Field: "ID"}}, &utils.NMSlice{ - &config.NMItem{Data: "1003", Path: []string{utils.AccountField + "[1]", "ID"}, - Config: tplFlds[2]}}) + eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + eMp.Set([]string{utils.AccountField, "0", "ID"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField + "[0]", "ID"}}}}) + eMp.Set([]string{utils.AccountField, "1", "ID"}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1003", Path: []string{utils.AccountField + "[1]", "ID"}}}}) b.ResetTimer() for i := 0; i < b.N; i++ { agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: utils.PathItems{{Field: utils.ToR}}}, utils.NewNMData(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: utils.PathItems{{Field: utils.AccountField}}}, utils.NewNMData("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: utils.PathItems{{Field: utils.Destination}}}, utils.NewNMData("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: utils.PathItems{{Field: utils.AnswerTime}}}, utils.NewNMData( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: utils.PathItems{{Field: utils.RequestType}}}, utils.NewNMData(utils.MetaPrepaid)) - agReq.CGRReply = &utils.NavigableMap{} + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} if err := agReq.SetFields(tplFlds); err != nil { b.Error(err) diff --git a/agents/diamagent.go b/agents/diamagent.go index adc537662..3c9acc9ff 100644 --- a/agents/diamagent.go +++ b/agents/diamagent.go @@ -198,14 +198,17 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) { return } diamDP := newDADataProvider(c, m) - reqVars := utils.NavigableMap{ - utils.OriginHost: utils.NewNMData(da.cgrCfg.DiameterAgentCfg().OriginHost), // used in templates - utils.OriginRealm: utils.NewNMData(da.cgrCfg.DiameterAgentCfg().OriginRealm), - utils.ProductName: utils.NewNMData(da.cgrCfg.DiameterAgentCfg().ProductName), - utils.MetaApp: utils.NewNMData(dApp.Name), - utils.MetaAppID: utils.NewNMData(dApp.ID), - utils.MetaCmd: utils.NewNMData(dCmd.Short + "R"), - utils.RemoteHost: utils.NewNMData(c.RemoteAddr().String()), + reqVars := &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.OriginHost: utils.NewLeafNode(da.cgrCfg.DiameterAgentCfg().OriginHost), // used in templates + utils.OriginRealm: utils.NewLeafNode(da.cgrCfg.DiameterAgentCfg().OriginRealm), + utils.ProductName: utils.NewLeafNode(da.cgrCfg.DiameterAgentCfg().ProductName), + utils.MetaApp: utils.NewLeafNode(dApp.Name), + utils.MetaAppID: utils.NewLeafNode(dApp.ID), + utils.MetaCmd: utils.NewLeafNode(dCmd.Short + "R"), + utils.RemoteHost: utils.NewLeafNode(c.RemoteAddr().String()), + }, } // build the negative error answer diamErr, err := diamErr( @@ -258,16 +261,16 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) { da.aReqsLck.Unlock() }() } - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := new(utils.DataNode) + opts := utils.MapStorage{} rply := utils.NewOrderedNavigableMap() // share it among different processors - opts := utils.NewOrderedNavigableMap() var processed bool for _, reqProcessor := range da.cgrCfg.DiameterAgentCfg().RequestProcessors { var lclProcessed bool lclProcessed, err = da.processRequest( reqProcessor, NewAgentRequest( - diamDP, reqVars, &cgrRplyNM, rply, opts, + diamDP, reqVars, cgrRplyNM, rply, opts, reqProcessor.Tenant, da.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, da.cgrCfg.GeneralCfg().DefaultTimezone), @@ -370,9 +373,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1AuthorizeEvent, authArgs, rply) rply.SetMaxUsageNeeded(authArgs.GetMaxUsage) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaInitiate: initArgs := sessions.NewV1InitSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -388,9 +389,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1InitiateSession, initArgs, rply) rply.SetMaxUsageNeeded(initArgs.InitSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaUpdate: updateArgs := sessions.NewV1UpdateSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -401,9 +400,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, rply.SetMaxUsageNeeded(updateArgs.UpdateSession) err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1UpdateSession, updateArgs, rply) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaTerminate: terminateArgs := sessions.NewV1TerminateSessionArgs( reqProcessor.Flags.Has(utils.MetaAccounts), @@ -416,9 +413,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, var rply string err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1TerminateSession, terminateArgs, &rply) - if err = agReq.setCGRReply(nil, err); err != nil { - return - } + agReq.setCGRReply(nil, err) case utils.MetaMessage: msgArgs := sessions.NewV1ProcessMessageArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -445,9 +440,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } rply.SetMaxUsageNeeded(msgArgs.Debit) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaEvent: evArgs := &sessions.V1ProcessEventArgs{ Flags: reqProcessor.Flags.SliceFlags(), @@ -462,9 +455,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, } else if needsMaxUsage(reqProcessor.Flags[utils.MetaRALs]) { cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaCDRs: // allow CDR processing } // separate request so we can capture the Terminate/Event also here @@ -473,7 +464,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, var rplyCDRs string if err = da.connMgr.Call(da.cgrCfg.DiameterAgentCfg().SessionSConns, da, utils.SessionSv1ProcessCDR, cgrEv, &rplyCDRs); err != nil { - agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) + agReq.CGRReply.Map[utils.Error] = utils.NewLeafNode(err.Error()) } } if err = agReq.SetFields(reqProcessor.ReplyFields); err != nil { diff --git a/agents/diamagent_test.go b/agents/diamagent_test.go index 338a4c8f4..d3f315325 100644 --- a/agents/diamagent_test.go +++ b/agents/diamagent_test.go @@ -24,10 +24,9 @@ import ( "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" - - "github.com/cgrates/cgrates/sessions" ) func TestDAsSessionSClientIface(t *testing.T) { @@ -62,7 +61,7 @@ func TestProcessRequest(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filters := engine.NewFilterS(config.CgrConfig(), nil, dm) // no need for filterS but still try to configure the dm :D - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} rply := utils.NewOrderedNavigableMap() diamDP := utils.MapStorage{ "SessionId": "123456", @@ -112,14 +111,14 @@ func TestProcessRequest(t *testing.T) { for _, v := range reqProcessor.ReplyFields { v.ComputePath() } - reqVars := utils.NavigableMap{ - utils.OriginHost: utils.NewNMData(config.CgrConfig().DiameterAgentCfg().OriginHost), - utils.OriginRealm: utils.NewNMData(config.CgrConfig().DiameterAgentCfg().OriginRealm), - utils.ProductName: utils.NewNMData(config.CgrConfig().DiameterAgentCfg().ProductName), - utils.MetaApp: utils.NewNMData("appName"), - utils.MetaAppID: utils.NewNMData("appID"), - utils.MetaCmd: utils.NewNMData("cmdR"), - } + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.OriginHost: utils.NewLeafNode(config.CgrConfig().DiameterAgentCfg().OriginHost), + utils.OriginRealm: utils.NewLeafNode(config.CgrConfig().DiameterAgentCfg().OriginRealm), + utils.ProductName: utils.NewLeafNode(config.CgrConfig().DiameterAgentCfg().ProductName), + utils.MetaApp: utils.NewLeafNode("appName"), + utils.MetaAppID: utils.NewLeafNode("appID"), + utils.MetaCmd: utils.NewLeafNode("cmdR"), + }} sS := &testMockSessionConn{calls: map[string]func(arg interface{}, rply interface{}) error{ utils.SessionSv1RegisterInternalBiJSONConn: func(arg interface{}, rply interface{}) error { @@ -442,7 +441,7 @@ func TestProcessRequest(t *testing.T) { }, }} reqProcessor.Flags = utils.FlagsWithParamsFromSlice([]string{utils.MetaAuthorize, utils.MetaAccounts}) - agReq := NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, + agReq := NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -467,10 +466,10 @@ func TestProcessRequest(t *testing.T) { } reqProcessor.Flags = utils.FlagsWithParamsFromSlice([]string{utils.MetaInitiate, utils.MetaAccounts, utils.MetaAttributes}) - cgrRplyNM = utils.NavigableMap{} + cgrRplyNM = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -484,10 +483,10 @@ func TestProcessRequest(t *testing.T) { } reqProcessor.Flags = utils.FlagsWithParamsFromSlice([]string{utils.MetaUpdate, utils.MetaAccounts, utils.MetaAttributes}) - cgrRplyNM = utils.NavigableMap{} + cgrRplyNM = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -507,10 +506,10 @@ func TestProcessRequest(t *testing.T) { for _, v := range reqProcessor.ReplyFields { v.ComputePath() } - cgrRplyNM = utils.NavigableMap{} + cgrRplyNM = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) @@ -524,10 +523,10 @@ func TestProcessRequest(t *testing.T) { } reqProcessor.Flags = utils.FlagsWithParamsFromSlice([]string{utils.MetaMessage, utils.MetaAccounts, utils.MetaAttributes}) - cgrRplyNM = utils.NavigableMap{} + cgrRplyNM = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} rply = utils.NewOrderedNavigableMap() - agReq = NewAgentRequest(diamDP, reqVars, &cgrRplyNM, rply, nil, + agReq = NewAgentRequest(diamDP, reqVars, cgrRplyNM, rply, nil, reqProcessor.Tenant, config.CgrConfig().GeneralCfg().DefaultTenant, config.CgrConfig().GeneralCfg().DefaultTimezone, filters, nil, nil) diff --git a/agents/dnsagent.go b/agents/dnsagent.go index 0f1836f9e..a84c67b0d 100644 --- a/agents/dnsagent.go +++ b/agents/dnsagent.go @@ -89,14 +89,19 @@ func (da *DNSAgent) Reload() (err error) { // requests are reaching here asynchronously func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) { dnsDP := newDNSDataProvider(req, w) - reqVars := make(utils.NavigableMap) - reqVars[QueryType] = utils.NewNMData(dns.TypeToString[req.Question[0].Qtype]) + reqVars := &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + QueryType: utils.NewLeafNode(dns.TypeToString[req.Question[0].Qtype]), + utils.RemoteHost: utils.NewLeafNode(w.RemoteAddr().String()), + }, + } rply := new(dns.Msg) rply.SetReply(req) // message preprocesing switch req.Question[0].Qtype { case dns.TypeNAPTR: - reqVars[QueryName] = utils.NewNMData(req.Question[0].Name) + reqVars.Map[QueryName] = utils.NewLeafNode(req.Question[0].Name) e164, err := e164FromNAPTR(req.Question[0].Name) if err != nil { utils.Logger.Warning( @@ -106,13 +111,12 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) { dnsWriteMsg(w, rply) return } - reqVars[E164Address] = utils.NewNMData(e164) - reqVars[DomainName] = utils.NewNMData(domainNameFromNAPTR(req.Question[0].Name)) + reqVars.Map[E164Address] = utils.NewLeafNode(e164) + reqVars.Map[DomainName] = utils.NewLeafNode(domainNameFromNAPTR(req.Question[0].Name)) } - reqVars[utils.RemoteHost] = utils.NewNMData(w.RemoteAddr().String()) - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} rplyNM := utils.NewOrderedNavigableMap() // share it among different processors - opts := utils.NewOrderedNavigableMap() + opts := utils.MapStorage{} var processed bool var err error for _, reqProcessor := range da.cgrCfg.DNSAgentCfg().RequestProcessors { @@ -120,7 +124,7 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) { lclProcessed, err = da.processRequest( reqProcessor, NewAgentRequest( - dnsDP, reqVars, &cgrRplyNM, rplyNM, + dnsDP, reqVars, cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, da.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(da.cgrCfg.DNSAgentCfg().Timezone, @@ -231,9 +235,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, utils.SessionSv1AuthorizeEvent, authArgs, rply) rply.SetMaxUsageNeeded(authArgs.GetMaxUsage) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaInitiate: initArgs := sessions.NewV1InitSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -250,9 +252,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, utils.SessionSv1InitiateSession, initArgs, rply) rply.SetMaxUsageNeeded(initArgs.InitSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaUpdate: updateArgs := sessions.NewV1UpdateSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -264,9 +264,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, utils.SessionSv1UpdateSession, updateArgs, rply) rply.SetMaxUsageNeeded(updateArgs.UpdateSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaTerminate: terminateArgs := sessions.NewV1TerminateSessionArgs( reqProcessor.Flags.Has(utils.MetaAccounts), @@ -280,9 +278,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, err = da.connMgr.Call(da.cgrCfg.DNSAgentCfg().SessionSConns, nil, utils.SessionSv1TerminateSession, terminateArgs, &rply) - if err = agReq.setCGRReply(nil, err); err != nil { - return - } + agReq.setCGRReply(nil, err) case utils.MetaMessage: evArgs := sessions.NewV1ProcessMessageArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -309,9 +305,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } rply.SetMaxUsageNeeded(evArgs.Debit) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaEvent: evArgs := &sessions.V1ProcessEventArgs{ Flags: reqProcessor.Flags.SliceFlags(), @@ -327,9 +321,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, } else if needsMaxUsage(reqProcessor.Flags[utils.MetaRALs]) { cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaCDRs: // allow CDR processing } // separate request so we can capture the Terminate/Event also here @@ -339,7 +331,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, if err = da.connMgr.Call(da.cgrCfg.DNSAgentCfg().SessionSConns, nil, utils.SessionSv1ProcessCDR, cgrEv, &rplyCDRs); err != nil { - agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) + agReq.CGRReply.Map[utils.Error] = utils.NewLeafNode(err.Error()) } } if err := agReq.SetFields(reqProcessor.ReplyFields); err != nil { diff --git a/agents/httpagent.go b/agents/httpagent.go index 8b072b1d7..5bd8e7110 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -63,12 +63,12 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) { utils.HTTPAgent, err.Error())) return } - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := &utils.DataNode{Type: utils.NMMapType, Map: make(map[string]*utils.DataNode)} rplyNM := utils.NewOrderedNavigableMap() - opts := utils.NewOrderedNavigableMap() - reqVars := utils.NavigableMap{utils.RemoteHost: utils.NewNMData(req.RemoteAddr)} + opts := utils.MapStorage{} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.RemoteHost: utils.NewLeafNode(req.RemoteAddr)}} for _, reqProcessor := range ha.reqProcessors { - agReq := NewAgentRequest(dcdr, reqVars, &cgrRplyNM, rplyNM, + agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, ha.dfltTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), @@ -167,9 +167,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1AuthorizeEvent, authArgs, rply) rply.SetMaxUsageNeeded(authArgs.GetMaxUsage) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaInitiate: initArgs := sessions.NewV1InitSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -185,9 +183,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1InitiateSession, initArgs, rply) rply.SetMaxUsageNeeded(initArgs.InitSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaUpdate: updateArgs := sessions.NewV1UpdateSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -198,9 +194,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1UpdateSession, updateArgs, rply) rply.SetMaxUsageNeeded(updateArgs.UpdateSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaTerminate: terminateArgs := sessions.NewV1TerminateSessionArgs( reqProcessor.Flags.Has(utils.MetaAccounts), @@ -213,9 +207,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, var rply string err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1TerminateSession, terminateArgs, &rply) - if err = agReq.setCGRReply(nil, err); err != nil { - return - } + agReq.setCGRReply(nil, err) case utils.MetaMessage: evArgs := sessions.NewV1ProcessMessageArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -241,9 +233,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } rply.SetMaxUsageNeeded(evArgs.Debit) - if err = agReq.setCGRReply(nil, err); err != nil { - return - } + agReq.setCGRReply(nil, err) case utils.MetaEvent: evArgs := &sessions.V1ProcessEventArgs{ Flags: reqProcessor.Flags.SliceFlags(), @@ -258,9 +248,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, } else if needsMaxUsage(reqProcessor.Flags[utils.MetaRALs]) { cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaCDRs: // allow CDR processing } // separate request so we can capture the Terminate/Event also here @@ -269,7 +257,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, var rplyCDRs string if err = ha.connMgr.Call(ha.sessionConns, nil, utils.SessionSv1ProcessCDR, cgrEv, &rplyCDRs); err != nil { - agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) + agReq.CGRReply.Map[utils.Error] = utils.NewLeafNode(err.Error()) } } if err := agReq.SetFields(reqProcessor.ReplyFields); err != nil { diff --git a/agents/libdiam.go b/agents/libdiam.go index fb66f992a..310896dca 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -430,22 +430,18 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err func updateDiamMsgFromNavMap(m *diam.Message, navMp *utils.OrderedNavigableMap, tmz string) (err error) { // write reply into message for el := navMp.GetFirstElement(); el != nil; el = el.Next() { - val := el.Value - var nmIt utils.NMInterface - if nmIt, err = navMp.Field(val); err != nil { + path := el.Value + var nmIt *utils.DataLeaf + if nmIt, err = navMp.Field(path); err != nil { return } - itm, isNMItem := nmIt.(*config.NMItem) - if !isNMItem { - return fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val)) - } - if itm == nil { + if nmIt == nil { continue // all attributes, not writable to diameter packet } if err = messageSetAVPsWithPath(m, - itm.Path, utils.IfaceAsString(itm.Data), - itm.Config != nil && itm.Config.NewBranch, tmz); err != nil { - return fmt.Errorf("setting item with path: %+v got err: %s", itm.Path, err.Error()) + nmIt.Path, nmIt.String(), + nmIt.NewBranch, tmz); err != nil { + return fmt.Errorf("setting item with path: %+v got err: %s", nmIt.Path, err.Error()) } } return @@ -466,7 +462,7 @@ func diamAnswer(m *diam.Message, resCode uint32, errFlag bool, // negDiamAnswer is used to return the negative answer we need previous to func diamErr(m *diam.Message, resCode uint32, - reqVars utils.NavigableMap, + reqVars *utils.DataNode, tpl []*config.FCTemplate, tnt, tmz string, filterS *engine.FilterS) (a *diam.Message, err error) { aReq := NewAgentRequest( @@ -502,5 +498,5 @@ func disectDiamListen(addrs string) (ipAddrs []net.IP) { type diamMsgData struct { c diam.Conn m *diam.Message - vars utils.NavigableMap + vars *utils.DataNode } diff --git a/agents/libdiam_test.go b/agents/libdiam_test.go index 098700a90..e62b1f7b4 100644 --- a/agents/libdiam_test.go +++ b/agents/libdiam_test.go @@ -25,9 +25,8 @@ import ( "testing" "time" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" "github.com/fiorix/go-diameter/v4/diam" "github.com/fiorix/go-diameter/v4/diam/avp" @@ -430,32 +429,32 @@ func TestUpdateDiamMsgFromNavMap1(t *testing.T) { ) nM := utils.NewOrderedNavigableMap() - itm := &config.NMItem{ + itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) @@ -514,43 +513,43 @@ func TestUpdateDiamMsgFromNavMap2(t *testing.T) { ) nM := utils.NewOrderedNavigableMap() - itm := &config.NMItem{ + itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, - Data: "http://172.10.88.88/", - Config: &config.FCTemplate{NewBranch: true}, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ + Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, + Data: "http://172.10.88.88/", + NewBranch: true, + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), - } - nM.Set( + }} + nM.Append( &utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems([]string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type[1]"}), - }, itm) + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, + }, itm.Value) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) } @@ -586,41 +585,41 @@ func TestUpdateDiamMsgFromNavMap3(t *testing.T) { nM := utils.NewOrderedNavigableMap() - itm := &config.NMItem{ + itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, Data: datatype.Enumerated(1), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) @@ -679,60 +678,60 @@ func TestUpdateDiamMsgFromNavMap4(t *testing.T) { nM := utils.NewOrderedNavigableMap() - itm := &config.NMItem{ + itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, Data: datatype.Enumerated(1), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) - itm2 := &config.NMItem{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, - Data: "http://172.10.88.88/", - Config: &config.FCTemplate{NewBranch: true}, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm, itm2}) + itm2 := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ + Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, + Data: "http://172.10.88.88/", + NewBranch: true, + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm, itm2}) - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{"Granted-Service-Unit", "CC-Time"}, Data: datatype.Unsigned32(10), - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) diff --git a/agents/libdns.go b/agents/libdns.go index 4578fec5b..64db5229e 100644 --- a/agents/libdns.go +++ b/agents/libdns.go @@ -24,7 +24,6 @@ import ( "net" "strings" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" "github.com/miekg/dns" ) @@ -156,15 +155,11 @@ func appendDNSAnswer(msg *dns.Msg) (err error) { func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) { msgFields := make(utils.StringSet) // work around to NMap issue for el := nm.GetFirstElement(); el != nil; el = el.Next() { - val := el.Value - var nmIt utils.NMInterface - if nmIt, err = nm.Field(val); err != nil { + path := el.Value + var cfgItm *utils.DataLeaf + if cfgItm, err = nm.Field(path); err != nil { return } - cfgItm, cast := nmIt.(*config.NMItem) - if !cast { - return fmt.Errorf("cannot cast val: %s into *config.NMItem", nmIt) - } if len(cfgItm.Path) == 0 { return errors.New("empty path in config item") } diff --git a/agents/libdns_test.go b/agents/libdns_test.go index 46c06ec1a..0f6efbe59 100644 --- a/agents/libdns_test.go +++ b/agents/libdns_test.go @@ -23,7 +23,6 @@ import ( "strings" "testing" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" "github.com/miekg/dns" ) @@ -177,76 +176,69 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { m.SetQuestion("3.6.9.4.7.1.7.1.5.6.8.9.4.e164.arpa.", dns.TypeNAPTR) nM := utils.NewOrderedNavigableMap() - itm := &config.NMItem{ + itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{}, Data: "Val1", - } - nM.Set(&utils.FullPath{Path: "Path", PathItems: utils.PathItems{{Field: "Path"}}}, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{Path: "Path", PathItems: []string{"Path"}}, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != "empty path in config item" { t.Error(err) } nM = utils.NewOrderedNavigableMap() - nM.Set(&utils.FullPath{Path: "Path", PathItems: utils.PathItems{{Field: "Path"}}}, utils.NewNMData("test")) - if err := updateDNSMsgFromNM(m, nM); err == nil || - err.Error() != `cannot cast val: test into *config.NMItem` { - t.Error(err) - } - - nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Rcode}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err != nil { - t.Error(err) + t.Fatal(err) } if m.Rcode != 10 { t.Errorf("expecting: <10>, received: <%+v>", m.Rcode) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Rcode}, Data: "RandomValue", - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Order}, Data: "RandomValue", - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Preference}, Data: "RandomValue", - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { t.Error(err) @@ -255,84 +247,84 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { m = new(dns.Msg) m.SetQuestion("3.6.9.4.7.1.7.1.5.6.8.9.4.e164.arpa.", dns.TypeA) nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Order}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Preference}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Flags}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Service}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Regexp}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) } nM = utils.NewOrderedNavigableMap() - itm = &config.NMItem{ + itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ Path: []string{utils.Replacement}, Data: 10, - } - nM.Set(&utils.FullPath{ - Path: strings.Join(itm.Path, utils.NestingSep), - PathItems: utils.NewPathItems(itm.Path), - }, &utils.NMSlice{itm}) + }} + nM.SetAsSlice(&utils.FullPath{ + Path: strings.Join(itm.Value.Path, utils.NestingSep), + PathItems: itm.Value.Path, + }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { t.Error(err) diff --git a/agents/libhttpagent.go b/agents/libhttpagent.go index fc06412ea..ae83a80e6 100644 --- a/agents/libhttpagent.go +++ b/agents/libhttpagent.go @@ -140,9 +140,7 @@ func (hU *httpXmlDP) FieldAsInterface(fldPath []string) (data interface{}, err e err = nil // cancel previous err var slctrStr string workPath := make([]string, len(fldPath)) - for i, val := range fldPath { - workPath[i] = val - } + copy(workPath, fldPath) for i := range workPath { if sIdx := strings.Index(workPath[i], "["); sIdx != -1 { slctrStr = workPath[i][sIdx:] @@ -247,17 +245,14 @@ func (xE *haTextPlainEncoder) Encode(nM *utils.OrderedNavigableMap) (err error) var str, nmPath string msgFields := make(map[string]string) // work around to NMap issue for el := nM.GetFirstElement(); el != nil; el = el.Next() { - val := el.Value - var nmIt utils.NMInterface - if nmIt, err = nM.Field(val); err != nil { + path := el.Value + var nmIt *utils.DataLeaf + if nmIt, err = nM.Field(path); err != nil { return } - nmItem, isNMItems := nmIt.(*config.NMItem) - if !isNMItems { - return fmt.Errorf("value: %s is not *NMItem", val) - } - nmPath = strings.Join(nmItem.Path, utils.NestingSep) - msgFields[utils.ConcatenatedKey(nmPath, utils.IfaceAsString(nmItem.Data))] = utils.IfaceAsString(nmItem.Data) + nmPath = strings.Join(nmIt.Path, utils.NestingSep) + val := nmIt.String() + msgFields[utils.ConcatenatedKey(nmPath, val)] = val } for key, val := range msgFields { str += fmt.Sprintf("%s=%s\n", strings.Split(key, utils.InInFieldSep)[0], val) diff --git a/agents/librad.go b/agents/librad.go index 2111026cf..7129424e9 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -19,10 +19,8 @@ along with this program. If not, see package agents import ( - "fmt" "net" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" "github.com/cgrates/radigo" ) @@ -31,14 +29,10 @@ import ( func radReplyAppendAttributes(reply *radigo.Packet, rplNM *utils.OrderedNavigableMap) (err error) { for el := rplNM.GetFirstElement(); el != nil; el = el.Next() { val := el.Value - var nmIt utils.NMInterface - if nmIt, err = rplNM.Field(val); err != nil { + var cfgItm *utils.DataLeaf + if cfgItm, err = rplNM.Field(val); err != nil { return } - cfgItm, cast := nmIt.(*config.NMItem) - if !cast { - return fmt.Errorf("cannot cast val: %s into *config.NMItem", nmIt) - } if cfgItm.Path[0] == MetaRadReplyCode { // Special case used to control the reply code of RADIUS reply if err = reply.SetCodeWithName(utils.IfaceAsString(cfgItm.Data)); err != nil { @@ -117,17 +111,18 @@ func (pk *radiusDP) RemoteHost() net.Addr { //radauthReq is used to authorize a request based on flags func radauthReq(flags utils.FlagsWithParams, req *radigo.Packet, aReq *AgentRequest, rpl *radigo.Packet) (bool, error) { // try to get UserPassword from Vars as slice of NMItems - nmItems, err := aReq.Vars.FieldAsInterface([]string{utils.UserPassword}) - if err != nil { - return false, err + nmItems, has := aReq.Vars.Map[utils.UserPassword] + if !has { + return false, utils.ErrNotFound } + pass := nmItems.Slice[0].Value.String() switch { case flags.Has(utils.MetaPAP): userPassAvps := req.AttributesWithName(UserPasswordAVP, utils.EmptyString) if len(userPassAvps) == 0 { return false, utils.NewErrMandatoryIeMissing(UserPasswordAVP) } - if userPassAvps[0].StringValue != (*nmItems.(*utils.NMSlice))[0].Interface() { + if userPassAvps[0].StringValue != pass { return false, nil } case flags.Has(utils.MetaCHAP): @@ -135,7 +130,7 @@ func radauthReq(flags utils.FlagsWithParams, req *radigo.Packet, aReq *AgentRequ if len(chapAVPs) == 0 { return false, utils.NewErrMandatoryIeMissing(CHAPPasswordAVP) } - return radigo.AuthenticateCHAP([]byte(utils.IfaceAsString((*nmItems.(*utils.NMSlice))[0].Interface())), + return radigo.AuthenticateCHAP([]byte(pass), req.Authenticator[:], chapAVPs[0].RawValue), nil case flags.Has(utils.MetaMSCHAPV2): msChallenge := req.AttributesWithName(MSCHAPChallengeAVP, MicrosoftVendor) @@ -150,7 +145,7 @@ func radauthReq(flags utils.FlagsWithParams, req *radigo.Packet, aReq *AgentRequ vsaMSChallange := msChallenge[0].Value.(*radigo.VSA) userName := req.AttributesWithName("User-Name", utils.EmptyString)[0].StringValue - passwordFromAttributes := utils.IfaceAsString((*nmItems.(*utils.NMSlice))[0].Interface()) + passwordFromAttributes := pass if len(vsaMSChallange.RawValue) != 16 || len(vsaMSResponde.RawValue) != 50 { return false, nil diff --git a/agents/librad_test.go b/agents/librad_test.go index 61eaf138d..0c46ebd53 100644 --- a/agents/librad_test.go +++ b/agents/librad_test.go @@ -90,9 +90,9 @@ func TestRadReplyAppendAttributes(t *testing.T) { v.ComputePath() } agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", nil, nil, nil) - agReq.CGRReply.Set(utils.NewPathItems([]string{utils.CapMaxUsage}), utils.NewNMData(time.Hour)) - agReq.CGRReply.Set(utils.NewPathItems([]string{utils.CapAttributes, "RadReply"}), utils.NewNMData("AccessAccept")) - agReq.CGRReply.Set(utils.NewPathItems([]string{utils.CapAttributes, utils.AccountField}), utils.NewNMData("1001")) + agReq.CGRReply.Set([]string{utils.CapMaxUsage}, utils.NewLeafNode(time.Hour)) + agReq.CGRReply.Set([]string{utils.CapAttributes, "RadReply"}, utils.NewLeafNode("AccessAccept")) + agReq.CGRReply.Set([]string{utils.CapAttributes, utils.AccountField}, utils.NewLeafNode("1001")) if err := agReq.SetFields(rplyFlds); err != nil { t.Error(err) diff --git a/agents/libsip.go b/agents/libsip.go index 5b0aea0f6..7b61f6096 100644 --- a/agents/libsip.go +++ b/agents/libsip.go @@ -33,14 +33,10 @@ func updateSIPMsgFromNavMap(m sipingo.Message, navMp *utils.OrderedNavigableMap) // write reply into message for el := navMp.GetFirstElement(); el != nil; el = el.Next() { val := el.Value - var nmIt utils.NMInterface - if nmIt, err = navMp.Field(val); err != nil { + var itm *utils.DataLeaf + if itm, err = navMp.Field(val); err != nil { return } - itm, isNMItem := nmIt.(*config.NMItem) - if !isNMItem { - return fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val)) - } if itm == nil { continue // all attributes, not writable to diameter packet } @@ -50,7 +46,7 @@ func updateSIPMsgFromNavMap(m sipingo.Message, navMp *utils.OrderedNavigableMap) } func sipErr(m utils.DataProvider, sipMessage sipingo.Message, - reqVars utils.NavigableMap, + reqVars *utils.DataNode, tpl []*config.FCTemplate, tnt, tmz string, filterS *engine.FilterS) (a sipingo.Message, err error) { aReq := NewAgentRequest( diff --git a/agents/libsip_test.go b/agents/libsip_test.go index aa1fe5c18..32178e7a9 100644 --- a/agents/libsip_test.go +++ b/agents/libsip_test.go @@ -42,9 +42,9 @@ func TestUpdateSIPMsgFromNavMap(t *testing.T) { v.ComputePath() } agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", nil, nil, nil) - agReq.CGRReply.Set(utils.NewPathItems([]string{utils.CapMaxUsage}), utils.NewNMData(time.Hour)) - agReq.CGRReply.Set(utils.NewPathItems([]string{utils.CapAttributes, "Request"}), utils.NewNMData("SIP/2.0 302 Moved Temporarily")) - agReq.CGRReply.Set(utils.NewPathItems([]string{utils.CapAttributes, utils.AccountField}), utils.NewNMData("1001")) + agReq.CGRReply.Set([]string{utils.CapMaxUsage}, utils.NewLeafNode(time.Hour)) + agReq.CGRReply.Set([]string{utils.CapAttributes, "Request"}, utils.NewLeafNode("SIP/2.0 302 Moved Temporarily")) + agReq.CGRReply.Set([]string{utils.CapAttributes, utils.AccountField}, utils.NewLeafNode("1001")) if err := agReq.SetFields(rplyFlds); err != nil { t.Error(err) @@ -60,16 +60,3 @@ func TestUpdateSIPMsgFromNavMap(t *testing.T) { t.Errorf("Expected: %s , received: %s", expected, m) } } - -func TestUpdateSIPMsgFromNavMap2(t *testing.T) { - m := sipingo.Message{} - mv := utils.NewOrderedNavigableMap() - var nm *config.NMItem - mv.Set(&utils.FullPath{PathItems: utils.NewPathItems([]string{utils.CapAttributes, utils.AccountField}), Path: utils.CapAttributes + utils.NestingSep + utils.AccountField}, nm) - mv.Set(&utils.FullPath{PathItems: utils.NewPathItems([]string{utils.CapMaxUsage}), Path: utils.CapMaxUsage}, utils.NewNMData(time.Hour)) - - expectedErr := `cannot encode reply value: [{"Field":"MaxUsage","Index":null}], err: not NMItems` - if err := updateSIPMsgFromNavMap(m, mv); err == nil || err.Error() != expectedErr { - t.Errorf("Expected error %s,received:%v", expectedErr, err) - } -} diff --git a/agents/radagent.go b/agents/radagent.go index ba34d28ea..6ee53b6fc 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -79,18 +79,18 @@ func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err e dcdr := newRADataProvider(req) // dcdr will provide information from request rpl = req.Reply() rpl.Code = radigo.AccessAccept - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := &utils.DataNode{} rplyNM := utils.NewOrderedNavigableMap() - opts := utils.NewOrderedNavigableMap() + opts := utils.MapStorage{} var processed bool - reqVars := utils.NavigableMap{utils.RemoteHost: utils.NewNMData(req.RemoteAddr().String())} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.RemoteHost: utils.NewLeafNode(req.RemoteAddr().String())}} for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { - agReq := NewAgentRequest(dcdr, reqVars, &cgrRplyNM, rplyNM, opts, + agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), ra.filterS, nil, nil) - agReq.Vars.Set(utils.PathItems{{Field: MetaRadReqType}}, utils.NewNMData(MetaRadAuth)) + agReq.Vars.Map[MetaRadReqType] = utils.NewLeafNode(MetaRadAuth) var lclProcessed bool if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq, rpl); lclProcessed { processed = lclProcessed @@ -124,13 +124,13 @@ func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err e dcdr := newRADataProvider(req) // dcdr will provide information from request rpl = req.Reply() rpl.Code = radigo.AccountingResponse - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := &utils.DataNode{} rplyNM := utils.NewOrderedNavigableMap() - opts := utils.NewOrderedNavigableMap() + opts := utils.MapStorage{} var processed bool - reqVars := utils.NavigableMap{utils.RemoteHost: utils.NewNMData(req.RemoteAddr().String())} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.RemoteHost: utils.NewLeafNode(req.RemoteAddr().String())}} for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { - agReq := NewAgentRequest(dcdr, reqVars, &cgrRplyNM, rplyNM, opts, + agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), @@ -225,9 +225,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1AuthorizeEvent, authArgs, rply) rply.SetMaxUsageNeeded(authArgs.GetMaxUsage) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaInitiate: initArgs := sessions.NewV1InitSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -243,9 +241,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1InitiateSession, initArgs, rply) rply.SetMaxUsageNeeded(initArgs.InitSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaUpdate: updateArgs := sessions.NewV1UpdateSessionArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -256,9 +252,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1UpdateSession, updateArgs, rply) rply.SetMaxUsageNeeded(updateArgs.UpdateSession) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaTerminate: terminateArgs := sessions.NewV1TerminateSessionArgs( reqProcessor.Flags.Has(utils.MetaAccounts), @@ -271,9 +265,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R var rply string err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1TerminateSession, terminateArgs, &rply) - if err = agReq.setCGRReply(nil, err); err != nil { - return - } + agReq.setCGRReply(nil, err) case utils.MetaMessage: evArgs := sessions.NewV1ProcessMessageArgs( reqProcessor.Flags.GetBool(utils.MetaAttributes), @@ -298,9 +290,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } rply.SetMaxUsageNeeded(evArgs.Debit) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaEvent: evArgs := &sessions.V1ProcessEventArgs{ Flags: reqProcessor.Flags.SliceFlags(), @@ -315,15 +305,13 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R } else if needsMaxUsage(reqProcessor.Flags[utils.MetaRALs]) { cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaCDRs: // allow this method case utils.MetaRadauth: if pass, err := radauthReq(reqProcessor.Flags, req, agReq, rpl); err != nil { - agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) + agReq.CGRReply.Map[utils.Error] = utils.NewLeafNode(err.Error()) } else if !pass { - agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(utils.RadauthFailed)) + agReq.CGRReply.Map[utils.Error] = utils.NewLeafNode(utils.RadauthFailed) } } // separate request so we can capture the Terminate/Event also here @@ -331,7 +319,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R var rplyCDRs string if err = ra.connMgr.Call(ra.cgrCfg.RadiusAgentCfg().SessionSConns, nil, utils.SessionSv1ProcessCDR, cgrEv, &rplyCDRs); err != nil { - agReq.CGRReply.Set(utils.PathItems{{Field: utils.Error}}, utils.NewNMData(err.Error())) + agReq.CGRReply.Map[utils.Error] = utils.NewLeafNode(err.Error()) } } diff --git a/agents/sipagent.go b/agents/sipagent.go index 2c8ca01a3..a12311bce 100644 --- a/agents/sipagent.go +++ b/agents/sipagent.go @@ -303,12 +303,15 @@ func (sa *SIPAgent) handleMessage(sipMessage sipingo.Message, remoteHost string) } dp := utils.MapStorage(sipMessageIface) var processed bool - cgrRplyNM := utils.NavigableMap{} + cgrRplyNM := &utils.DataNode{} rplyNM := utils.NewOrderedNavigableMap() - opts := utils.NewOrderedNavigableMap() - reqVars := utils.NavigableMap{ - utils.RemoteHost: utils.NewNMData(remoteHost), - method: utils.NewNMData(sipMessage.MethodFrom(requestHeader)), + opts := utils.MapStorage{} + reqVars := &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.RemoteHost: utils.NewLeafNode(remoteHost), + method: utils.NewLeafNode(sipMessage.MethodFrom(requestHeader)), + }, } // build the negative error answer sErr, err := sipErr( @@ -325,7 +328,7 @@ func (sa *SIPAgent) handleMessage(sipMessage sipingo.Message, remoteHost string) } for _, reqProcessor := range sa.cfg.SIPAgentCfg().RequestProcessors { - agReq := NewAgentRequest(dp, reqVars, &cgrRplyNM, rplyNM, + agReq := NewAgentRequest(dp, reqVars, cgrRplyNM, rplyNM, opts, reqProcessor.Tenant, sa.cfg.GeneralCfg().DefaultTenant, utils.FirstNonEmpty(reqProcessor.Timezone, config.CgrConfig().GeneralCfg().DefaultTimezone), @@ -357,7 +360,7 @@ func (sa *SIPAgent) handleMessage(sipMessage sipingo.Message, remoteHost string) utils.SIPAgent, sipMessage, remoteHost)) return } - if rplyNM.Len() == 0 { // if we do not populate the reply with any field we do not send any reply back + if rplyNM.Empty() { // if we do not populate the reply with any field we do not send any reply back return } if err = updateSIPMsgFromNavMap(sipMessage, rplyNM); err != nil { @@ -435,9 +438,7 @@ func (sa *SIPAgent) processRequest(reqProcessor *config.RequestProcessor, err = sa.connMgr.Call(sa.cfg.SIPAgentCfg().SessionSConns, nil, utils.SessionSv1AuthorizeEvent, authArgs, rply) rply.SetMaxUsageNeeded(authArgs.GetMaxUsage) - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) case utils.MetaEvent: evArgs := &sessions.V1ProcessEventArgs{ Flags: reqProcessor.Flags.SliceFlags(), @@ -453,9 +454,7 @@ func (sa *SIPAgent) processRequest(reqProcessor *config.RequestProcessor, } else if needsMaxUsage(reqProcessor.Flags[utils.MetaRALs]) { cgrEv.Event[utils.Usage] = rply.MaxUsage // make sure the CDR reflects the debit } - if err = agReq.setCGRReply(rply, err); err != nil { - return - } + agReq.setCGRReply(rply, err) } if err := agReq.SetFields(reqProcessor.ReplyFields); err != nil { return false, err diff --git a/config/fctemplate.go b/config/fctemplate.go index 745d862fd..a88fbb265 100644 --- a/config/fctemplate.go +++ b/config/fctemplate.go @@ -36,7 +36,7 @@ func NewFCTemplateFromFCTemplateJSONCfg(jsnCfg *FcTemplateJsonCfg, separator str if jsnCfg.Path != nil { fcTmp.Path = *jsnCfg.Path fcTmp.pathSlice = strings.Split(*jsnCfg.Path, utils.NestingSep) - fcTmp.pathItems = utils.NewPathItems(fcTmp.pathSlice) + fcTmp.pathItems = utils.CompilePathSlice(fcTmp.pathSlice) fcTmp.Tag = fcTmp.Path } fcTmp.Tag = fcTmp.Path @@ -118,8 +118,8 @@ type FCTemplate struct { RoundingDecimals *int MaskDestID string MaskLen int - pathItems utils.PathItems // Field identifier - pathSlice []string // Used when we set a NMItem to not recreate this slice for every itemsc + pathItems []string // Field identifier + pathSlice []string // Used when we set a NMItem to not recreate this slice for every itemsc } // FCTemplatesFromFCTemplatesJSONCfg will build a list of FCTemplates from json @@ -171,7 +171,7 @@ func (fc FCTemplate) Clone() (cln *FCTemplate) { Tag: fc.Tag, Type: fc.Type, Path: fc.Path, - pathItems: fc.pathItems.Clone(), + pathItems: utils.CloneSlice(fc.pathItems), Value: fc.Value.Clone(), Width: fc.Width, Strip: fc.Strip, @@ -285,14 +285,14 @@ func (fc *FCTemplate) GetPathSlice() []string { } // GetPathItems returns the cached path as PathItems -func (fc *FCTemplate) GetPathItems() utils.PathItems { +func (fc *FCTemplate) GetPathItems() []string { return fc.pathItems } // ComputePath used in test to populate private fields used to store the path func (fc *FCTemplate) ComputePath() { fc.pathSlice = strings.Split(fc.Path, utils.NestingSep) - fc.pathItems = utils.NewPathItems(fc.pathSlice) + fc.pathItems = utils.CompilePathSlice(fc.pathSlice) } // Clone returns a deep copy of FcTemplates diff --git a/config/fctemplate_test.go b/config/fctemplate_test.go index 9a67844b6..b88f00ca9 100644 --- a/config/fctemplate_test.go +++ b/config/fctemplate_test.go @@ -67,24 +67,7 @@ func TestFCTemplatePathItems(t *testing.T) { fcTemplate := FCTemplate{ Path: "*req.Account[1].Balance[*monetary].Value", } - expected := utils.PathItems{ - { - Field: "*req", - Index: nil, - }, - { - Field: "Account", - Index: []string{"1"}, - }, - { - Field: "Balance", - Index: []string{"*monetary"}, - }, - { - Field: "Value", - Index: nil, - }, - } + expected := []string{"*req", "Account", "1", "Balance", "*monetary", "Value"} fcTemplate.ComputePath() if !reflect.DeepEqual(expected, fcTemplate.GetPathItems()) { t.Errorf("Expected %+v, received %+v", utils.ToJSON(expected), utils.ToJSON(fcTemplate)) diff --git a/config/loaderscfg_test.go b/config/loaderscfg_test.go index 52e55bd23..fa6e6ef87 100644 --- a/config/loaderscfg_test.go +++ b/config/loaderscfg_test.go @@ -78,7 +78,7 @@ func TestLoaderSCfgloadFromJsonCfgCase1(t *testing.T) { Tag: "TenantID", Path: "Tenant", pathSlice: []string{"Tenant"}, - pathItems: utils.PathItems{{Field: "Tenant"}}, + pathItems: []string{"Tenant"}, Type: utils.MetaComposed, Value: val, Mandatory: true, @@ -422,7 +422,7 @@ func TestLoaderSCfgsClone(t *testing.T) { Tag: "TenantID", Path: "Tenant", pathSlice: []string{"Tenant"}, - pathItems: utils.PathItems{{Field: "Tenant"}}, + pathItems: []string{"Tenant"}, Type: utils.MetaComposed, Value: NewRSRParsersMustCompile("cgrate.org", utils.InfieldSep), Mandatory: true, diff --git a/config/navigablemap.go b/config/navigablemap.go index 0219155c0..e1ee933dd 100644 --- a/config/navigablemap.go +++ b/config/navigablemap.go @@ -20,65 +20,12 @@ package config import ( "encoding/xml" - "fmt" "strings" "time" "github.com/cgrates/cgrates/utils" ) -// NMItem is an item in the NavigableMap -type NMItem struct { - Path []string // path in map - Data interface{} // value of the element - Config *FCTemplate // so we can store additional configuration -} - -func (nmi *NMItem) String() string { - return utils.ToJSON(nmi) -} - -// Interface returns the wraped interface -func (nmi *NMItem) Interface() interface{} { - return nmi.Data -} - -// Field not implemented only used in order to implement the NM interface -func (nmi *NMItem) Field(path utils.PathItems) (val utils.NMInterface, err error) { - return nil, utils.ErrNotImplemented -} - -// Set not implemented only used in order to implement the NM interface -// special case when the path is empty the interface should be seted -// this is in order to modify the wraped interface -func (nmi *NMItem) Set(path utils.PathItems, val utils.NMInterface) (added bool, err error) { - if len(path) != 0 { - return false, utils.ErrWrongPath - } - nmi.Data = val.Interface() - return -} - -// Remove not implemented only used in order to implement the NM interface -func (nmi *NMItem) Remove(path utils.PathItems) (err error) { - return utils.ErrNotImplemented -} - -// Type returns the type of the NM interface -func (nmi *NMItem) Type() utils.NMType { - return utils.NMDataType -} - -// Empty returns true if the NM is empty(no data) -func (nmi *NMItem) Empty() bool { - return nmi == nil || nmi.Data == nil -} - -// Len not implemented only used in order to implement the NM interface -func (nmi *NMItem) Len() int { - return 0 -} - // XMLElement is specially crafted to be automatically marshalled by encoding/xml type XMLElement struct { XMLName xml.Name @@ -93,13 +40,8 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err pathIdx := make(map[string]*XMLElement) // Keep the index of elements based on path for el := nm.GetFirstElement(); el != nil; el = el.Next() { path := el.Value - var nmIt utils.NMInterface - nmIt, _ = nm.Field(path) // this should never return error cause we get the path from the order - nmItm, isNMItem := nmIt.(*NMItem) - if !isNMItem { - return nil, fmt.Errorf("value: %+v is not []*NMItem", path) - } - if nmItm.Config != nil && nmItm.Config.NewBranch { + nmItm, _ := nm.Field(path) // this should never return error cause we get the path from the order + if nmItm.NewBranch { pathIdx = make(map[string]*XMLElement) // reset cache so we can start having other elements with same path } val := utils.IfaceAsString(nmItm.Data) @@ -110,10 +52,10 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err continue } if i == len(nmItm.Path) { // lastElmnt, overwrite value or add attribute - if nmItm.Config != nil && nmItm.Config.AttributeID != "" { + if nmItm.AttributeID != "" { cachedElm.Attributes = append(cachedElm.Attributes, &xml.Attr{ - Name: xml.Name{Local: nmItm.Config.AttributeID}, + Name: xml.Name{Local: nmItm.AttributeID}, Value: val, }) } else { @@ -127,11 +69,10 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err elm := &XMLElement{XMLName: xml.Name{Local: nmItm.Path[j-1]}} pathIdx[strings.Join(nmItm.Path[:j], "")] = elm if newElm == nil { - if nmItm.Config != nil && - nmItm.Config.AttributeID != "" { + if nmItm.AttributeID != "" { elm.Attributes = append(elm.Attributes, &xml.Attr{ - Name: xml.Name{Local: nmItm.Config.AttributeID}, + Name: xml.Name{Local: nmItm.AttributeID}, Value: val, }) } else { @@ -151,11 +92,10 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err elm := &XMLElement{XMLName: xml.Name{Local: nmItm.Path[i-1]}} pathIdx[strings.Join(nmItm.Path[:i], "")] = elm if newElm == nil { // last element, create data inside - if nmItm.Config != nil && - nmItm.Config.AttributeID != "" { + if nmItm.AttributeID != "" { elm.Attributes = append(elm.Attributes, &xml.Attr{ - Name: xml.Name{Local: nmItm.Config.AttributeID}, + Name: xml.Name{Local: nmItm.AttributeID}, Value: val, }) } else { @@ -176,7 +116,7 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err // NMAsCGREvent builds a CGREvent considering Time as time.Now() // and Event as linear map[string]interface{} with joined paths // treats particular case when the value of map is []*NMItem - used in agents/AgentRequest -func NMAsCGREvent(nM *utils.OrderedNavigableMap, tnt string, pathSep string, opts *utils.OrderedNavigableMap) (cgrEv *utils.CGREvent) { +func NMAsCGREvent(nM *utils.OrderedNavigableMap, tnt string, pathSep string, opts utils.MapStorage) (cgrEv *utils.CGREvent) { if nM == nil { return } @@ -189,20 +129,16 @@ func NMAsCGREvent(nM *utils.OrderedNavigableMap, tnt string, pathSep string, opt ID: utils.UUIDSha1Prefix(), Time: utils.TimePointer(time.Now()), Event: make(map[string]interface{}), - APIOpts: NMAsMapInterface(opts, pathSep), + APIOpts: opts, } for ; el != nil; el = el.Next() { - branchPath := el.Value - val, _ := nM.Field(branchPath) // this should never return error cause we get the path from the order - opath := utils.GetPathWithoutIndex(branchPath.String()) - if nmItm, isNMItem := val.(*NMItem); isNMItem { // special case when we have added multiple items inside a key, used in agents - if nmItm.Config != nil && - nmItm.Config.AttributeID != "" { - continue - } + val, _ := nM.Field(el.Value) // this should never return error cause we get the path from the order + opath := utils.GetPathWithoutIndex(strings.Join(val.Path, utils.NestingSep)) + if val.AttributeID != "" { + continue } if _, has := cgrEv.Event[opath]; !has { - cgrEv.Event[opath] = val.Interface() // first item which is not an attribute will become the value + cgrEv.Event[opath] = val.Data // first item which is not an attribute will become the value } } return @@ -217,17 +153,13 @@ func NMAsMapInterface(nM *utils.OrderedNavigableMap, pathSep string) (mp map[str return } for ; el != nil; el = el.Next() { - branchPath := el.Value - val, _ := nM.Field(branchPath) // this should never return error cause we get the path from the order - opath := utils.GetPathWithoutIndex(branchPath.String()) - if nmItm, isNMItem := val.(*NMItem); isNMItem { // special case when we have added multiple items inside a key, used in agents - if nmItm.Config != nil && - nmItm.Config.AttributeID != "" { - continue - } + val, _ := nM.Field(el.Value) // this should never return error cause we get the path from the order + opath := utils.GetPathWithoutIndex(strings.Join(val.Path, utils.NestingSep)) + if val.AttributeID != "" { + continue } if _, has := mp[opath]; !has { - mp[opath] = val.Interface() // first item which is not an attribute will become the value + mp[opath] = val.Data // first item which is not an attribute will become the value } } return diff --git a/ees/elastic.go b/ees/elastic.go index ab88671f3..c9f0fa61f 100644 --- a/ees/elastic.go +++ b/ees/elastic.go @@ -154,8 +154,7 @@ func (eEe *ElasticEe) ExportEvent(cgrEv *utils.CGREvent) (err error) { } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - itm := nmIt.(*config.NMItem) - valMp[strings.Join(itm.Path, utils.NestingSep)] = utils.IfaceAsString(itm.Data) + valMp[strings.Join(nmIt.Path, utils.NestingSep)] = nmIt.String() } } updateEEMetrics(eEe.dc, cgrEv.Event, utils.FirstNonEmpty(eEe.cgrCfg.EEsCfg().Exporters[eEe.cfgIdx].Timezone, diff --git a/ees/httpjsonmap.go b/ees/httpjsonmap.go index c537e92b5..4f6336f80 100644 --- a/ees/httpjsonmap.go +++ b/ees/httpjsonmap.go @@ -100,8 +100,7 @@ func (httpEE *HTTPjsonMapEE) ExportEvent(cgrEv *utils.CGREvent) (err error) { } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - itm := nmIt.(*config.NMItem) - valMp[strings.Join(itm.Path, utils.NestingSep)] = utils.IfaceAsString(itm.Data) + valMp[strings.Join(nmIt.Path, utils.NestingSep)] = nmIt.String() } if hdr, err = httpEE.composeHeader(); err != nil { return @@ -147,8 +146,7 @@ func (httpEE *HTTPjsonMapEE) composeHeader() (hdr http.Header, err error) { } for el := eeReq.OrdNavMP[utils.MetaHdr].GetFirstElement(); el != nil; el = el.Next() { nmIt, _ := eeReq.OrdNavMP[utils.MetaHdr].Field(el.Value) //Safe to ignore error, since the path always exists - itm := nmIt.(*config.NMItem) //We only store nmItems in the map - hdr.Set(strings.Join(itm.Path, utils.NestingSep), utils.IfaceAsString(itm.Data)) + hdr.Set(strings.Join(nmIt.Path, utils.NestingSep), nmIt.String()) } return } diff --git a/ees/httppost.go b/ees/httppost.go index f252e0b27..93d678dd4 100644 --- a/ees/httppost.go +++ b/ees/httppost.go @@ -96,8 +96,7 @@ func (httpPost *HTTPPost) ExportEvent(cgrEv *utils.CGREvent) (err error) { } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - itm := nmIt.(*config.NMItem) - urlVals.Set(strings.Join(itm.Path, utils.NestingSep), utils.IfaceAsString(itm.Data)) + urlVals.Set(strings.Join(nmIt.Path, utils.NestingSep), nmIt.String()) } if hdr, err = httpPost.composeHeader(); err != nil { return @@ -141,8 +140,7 @@ func (httpPost *HTTPPost) composeHeader() (hdr http.Header, err error) { } for el := eeReq.OrdNavMP[utils.MetaHdr].GetFirstElement(); el != nil; el = el.Next() { nmIt, _ := eeReq.OrdNavMP[utils.MetaHdr].Field(el.Value) - itm := nmIt.(*config.NMItem) - hdr.Set(strings.Join(itm.Path, utils.NestingSep), utils.IfaceAsString(itm.Data)) + hdr.Set(strings.Join(nmIt.Path, utils.NestingSep), nmIt.String()) } return } diff --git a/ees/posterjsonmap.go b/ees/posterjsonmap.go index e57820a67..dd81d553c 100644 --- a/ees/posterjsonmap.go +++ b/ees/posterjsonmap.go @@ -111,8 +111,7 @@ func (pstrEE *PosterJSONMapEE) ExportEvent(cgrEv *utils.CGREvent) (err error) { } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - itm := nmIt.(*config.NMItem) - valMp[strings.Join(itm.Path, utils.NestingSep)] = utils.IfaceAsString(itm.Data) + valMp[strings.Join(nmIt.Path, utils.NestingSep)] = nmIt.String() } } updateEEMetrics(pstrEE.dc, cgrEv.Event, utils.FirstNonEmpty(pstrEE.cgrCfg.EEsCfg().Exporters[pstrEE.cfgIdx].Timezone, diff --git a/ees/sql.go b/ees/sql.go index 4cf616afb..2688f4b34 100644 --- a/ees/sql.go +++ b/ees/sql.go @@ -172,12 +172,12 @@ func (sqlEe *SQLEe) ExportEvent(cgrEv *utils.CGREvent) (err error) { } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { - iface, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - pathWithoutIndex := utils.GetPathWithoutIndex(el.Value.String()) + nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) + pathWithoutIndex := utils.GetPathWithoutIndex(strings.Join(el.Value, utils.NestingSep)) if pathWithoutIndex != utils.MetaRow { colNames = append(colNames, pathWithoutIndex) } - vals = append(vals, iface.Interface()) + vals = append(vals, nmIt.Data) } sqlValues := make([]string, len(vals)) diff --git a/engine/attributes.go b/engine/attributes.go index bcd90a47d..6a683caa5 100644 --- a/engine/attributes.go +++ b/engine/attributes.go @@ -427,7 +427,7 @@ func (alS *AttributeService) V1GetAttributeForEvent(args *AttrArgsProcessEvent, utils.MetaReq: args.CGREvent.Event, utils.MetaOpts: args.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, }, utils.EmptyString) if err != nil { @@ -463,7 +463,7 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent, utils.MetaReq: args.CGREvent.Event, utils.MetaOpts: args.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } var lastID string @@ -472,7 +472,7 @@ func (alS *AttributeService) V1ProcessEvent(args *AttrArgsProcessEvent, dynDP := newDynamicDP(alS.cgrcfg.AttributeSCfg().ResourceSConns, alS.cgrcfg.AttributeSCfg().StatSConns, alS.cgrcfg.AttributeSCfg().ApierSConns, args.Tenant, eNV) for i := 0; i < processRuns; i++ { - (eNV[utils.MetaVars].(utils.MapStorage))[utils.ProcessRuns] = utils.NewNMData(i + 1) + (eNV[utils.MetaVars].(utils.MapStorage))[utils.ProcessRuns] = i + 1 var evRply *AttrSProcessEventReply evRply, err = alS.processEvent(tnt, args, eNV, dynDP, lastID) if err != nil { diff --git a/engine/libroutes.go b/engine/libroutes.go index 55cfd9e37..4dcdb291e 100644 --- a/engine/libroutes.go +++ b/engine/libroutes.go @@ -181,29 +181,35 @@ func (sRoutes *SortedRoutes) Digest() string { return strings.Join(sRoutes.RoutesWithParams(), utils.FieldsSep) } -func (ss *SortedRoute) AsNavigableMap() (nm utils.NavigableMap) { - nm = utils.NavigableMap{ - utils.RouteID: utils.NewNMData(ss.RouteID), - utils.RouteParameters: utils.NewNMData(ss.RouteParameters), +func (ss *SortedRoute) AsNavigableMap() (nm *utils.DataNode) { + nm = &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.RouteID: utils.NewLeafNode(ss.RouteID), + utils.RouteParameters: utils.NewLeafNode(ss.RouteParameters), + }, } - sd := utils.NavigableMap{} + sd := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} for k, d := range ss.SortingData { - sd[k] = utils.NewNMData(d) + sd.Map[k] = utils.NewLeafNode(d) } - nm[utils.SortingData] = sd + nm.Map[utils.SortingData] = sd return } -func (sRoutes *SortedRoutes) AsNavigableMap() (nm utils.NavigableMap) { - nm = utils.NavigableMap{ - utils.ProfileID: utils.NewNMData(sRoutes.ProfileID), - utils.Sorting: utils.NewNMData(sRoutes.Sorting), +func (sRoutes *SortedRoutes) AsNavigableMap() (nm *utils.DataNode) { + nm = &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.ProfileID: utils.NewLeafNode(sRoutes.ProfileID), + utils.Sorting: utils.NewLeafNode(sRoutes.Sorting), + }, } - sr := make(utils.NMSlice, len(sRoutes.Routes)) + sr := make([]*utils.DataNode, len(sRoutes.Routes)) for i, ss := range sRoutes.Routes { sr[i] = ss.AsNavigableMap() } - nm[utils.CapRoutes] = &sr + nm.Map[utils.CapRoutes] = &utils.DataNode{Type: utils.NMSliceType, Slice: sr} return } @@ -278,10 +284,10 @@ func (sRs SortedRoutesList) Digest() string { } // AsNavigableMap returns the SortedRoutesSet as NMInterface object -func (sRs SortedRoutesList) AsNavigableMap() (nm utils.NMSlice) { - nm = make(utils.NMSlice, len(sRs)) +func (sRs SortedRoutesList) AsNavigableMap() (nm *utils.DataNode) { + nm = &utils.DataNode{Type: utils.NMSliceType, Slice: make([]*utils.DataNode, len(sRs))} for i, ss := range sRs { - nm[i] = ss.AsNavigableMap() + nm.Slice[i] = ss.AsNavigableMap() } return } diff --git a/engine/libroutes_test.go b/engine/libroutes_test.go index 62d9d1bef..e78deb462 100644 --- a/engine/libroutes_test.go +++ b/engine/libroutes_test.go @@ -1012,13 +1012,19 @@ func TestSortedRouteAsNavigableMap(t *testing.T) { utils.Weight: 15.5, }, } - expNavMap := utils.NavigableMap{ - utils.RouteID: utils.NewNMData("ROUTE1"), - utils.RouteParameters: utils.NewNMData("SORTING_PARAMETER"), - utils.SortingData: utils.NavigableMap{ - utils.Ratio: utils.NewNMData(6.0), - utils.Load: utils.NewNMData(10.0), - utils.Weight: utils.NewNMData(15.5), + expNavMap := &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.RouteID: utils.NewLeafNode("ROUTE1"), + utils.RouteParameters: utils.NewLeafNode("SORTING_PARAMETER"), + utils.SortingData: &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.Ratio: utils.NewLeafNode(6.0), + utils.Load: utils.NewLeafNode(10.0), + utils.Weight: utils.NewLeafNode(15.5), + }, + }, }, } if rcv := sSpls.AsNavigableMap(); !reflect.DeepEqual(rcv, expNavMap) { @@ -1051,25 +1057,43 @@ func TestSortedRoutesAsNavigableMap(t *testing.T) { }, } - expNavMap := utils.NavigableMap{ - utils.ProfileID: utils.NewNMData("TEST_ID1"), - utils.Sorting: utils.NewNMData(utils.MetaWeight), - utils.CapRoutes: &utils.NMSlice{ - utils.NavigableMap{ - utils.RouteID: utils.NewNMData("ROUTE1"), - utils.RouteParameters: utils.NewNMData("SORTING_PARAMETER"), - utils.SortingData: utils.NavigableMap{ - utils.Ratio: utils.NewNMData(6.0), - utils.Load: utils.NewNMData(10.0), - utils.Weight: utils.NewNMData(15.5), - }, - }, - utils.NavigableMap{ - utils.RouteID: utils.NewNMData("ROUTE2"), - utils.RouteParameters: utils.NewNMData("SORTING_PARAMETER_SECOND"), - utils.SortingData: utils.NavigableMap{ - utils.Ratio: utils.NewNMData(7.0), - utils.Load: utils.NewNMData(10.0), + expNavMap := &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.ProfileID: utils.NewLeafNode("TEST_ID1"), + utils.Sorting: utils.NewLeafNode(utils.MetaWeight), + utils.CapRoutes: &utils.DataNode{ + Type: utils.NMSliceType, + Slice: []*utils.DataNode{ + &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.RouteID: utils.NewLeafNode("ROUTE1"), + utils.RouteParameters: utils.NewLeafNode("SORTING_PARAMETER"), + utils.SortingData: &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.Ratio: utils.NewLeafNode(6.0), + utils.Load: utils.NewLeafNode(10.0), + utils.Weight: utils.NewLeafNode(15.5), + }, + }, + }, + }, + &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.RouteID: utils.NewLeafNode("ROUTE2"), + utils.RouteParameters: utils.NewLeafNode("SORTING_PARAMETER_SECOND"), + utils.SortingData: &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.Ratio: utils.NewLeafNode(7.0), + utils.Load: utils.NewLeafNode(10.0), + }, + }, + }, + }, }, }, }, diff --git a/engine/z_attributes_test.go b/engine/z_attributes_test.go index 97d0d13a9..3de16eb09 100644 --- a/engine/z_attributes_test.go +++ b/engine/z_attributes_test.go @@ -242,7 +242,7 @@ func TestAttributeProfileForEvent(t *testing.T) { utils.MetaReq: attrEvs[0].CGREvent.Event, utils.MetaOpts: attrEvs[0].APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, }, utils.EmptyString) if err != nil { @@ -256,7 +256,7 @@ func TestAttributeProfileForEvent(t *testing.T) { utils.MetaReq: attrEvs[1].CGREvent.Event, utils.MetaOpts: attrEvs[1].APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, }, utils.EmptyString) if err != nil { @@ -271,7 +271,7 @@ func TestAttributeProfileForEvent(t *testing.T) { utils.MetaReq: attrEvs[2].CGREvent.Event, utils.MetaOpts: attrEvs[2].APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, }, utils.EmptyString) if err != nil { @@ -293,7 +293,7 @@ func TestAttributeProcessEvent(t *testing.T) { utils.MetaReq: attrEvs[0].CGREvent.Event, utils.MetaOpts: attrEvs[0].APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } atrp, err := attrService.processEvent(attrEvs[0].Tenant, attrEvs[0], eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -311,7 +311,7 @@ func TestAttributeProcessEventWithNotFound(t *testing.T) { utils.MetaReq: attrEvs[3].CGREvent.Event, utils.MetaOpts: attrEvs[3].APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } if _, err := attrService.processEvent(attrEvs[0].Tenant, attrEvs[3], eNM, @@ -332,7 +332,7 @@ func TestAttributeProcessEventWithIDs(t *testing.T) { utils.MetaReq: attrEvs[3].CGREvent.Event, utils.MetaOpts: attrEvs[3].APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } if atrp, err := attrService.processEvent(attrEvs[0].Tenant, attrEvs[3], eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString); err != nil { @@ -1928,7 +1928,7 @@ func TestProcessAttributeConstant(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -1988,7 +1988,7 @@ func TestProcessAttributeVariable(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2055,7 +2055,7 @@ func TestProcessAttributeComposed(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2117,7 +2117,7 @@ func TestProcessAttributeUsageDifference(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2179,7 +2179,7 @@ func TestProcessAttributeSum(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2241,7 +2241,7 @@ func TestProcessAttributeDiff(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2303,7 +2303,7 @@ func TestProcessAttributeMultiply(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2365,7 +2365,7 @@ func TestProcessAttributeDivide(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2427,7 +2427,7 @@ func TestProcessAttributeValueExponent(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2489,7 +2489,7 @@ func TestProcessAttributeUnixTimeStamp(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2550,7 +2550,7 @@ func TestProcessAttributePrefix(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) @@ -2611,7 +2611,7 @@ func TestProcessAttributeSuffix(t *testing.T) { utils.MetaReq: ev.CGREvent.Event, utils.MetaOpts: ev.APIOpts, utils.MetaVars: utils.MapStorage{ - utils.ProcessRuns: utils.NewNMData(0), + utils.ProcessRuns: 0, }, } rcv, err := attrService.processEvent(ev.Tenant, ev, eNM, newDynamicDP(nil, nil, nil, "cgrates.org", eNM), utils.EmptyString) diff --git a/ers/filecsv.go b/ers/filecsv.go index 272540ffd..2837e4a8f 100644 --- a/ers/filecsv.go +++ b/ers/filecsv.go @@ -141,7 +141,7 @@ func (rdr *CSVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := utils.NavigableMap{utils.FileName: utils.NewNMData(fName)} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} for { var record []string if record, err = csvReader.Read(); err != nil { diff --git a/ers/filefwv.go b/ers/filefwv.go index 5b5334a9e..f0e7ade78 100644 --- a/ers/filefwv.go +++ b/ers/filefwv.go @@ -140,7 +140,7 @@ func (rdr *FWVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := utils.NavigableMap{utils.FileName: utils.NewNMData(fName)} + reqVars := &utils.DataNode{Type:utils.NMMapType,Map:map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} for { var hasHeader, hasTrailer bool diff --git a/ers/filejson.go b/ers/filejson.go index 37d05210c..6c9c3df98 100644 --- a/ers/filejson.go +++ b/ers/filejson.go @@ -142,7 +142,7 @@ func (rdr *JSONFileER) processFile(fPath, fName string) (err error) { } evsPosted := 0 - reqVars := utils.NavigableMap{utils.FileName: utils.NewNMData(fName)} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} agReq := agents.NewAgentRequest( utils.MapStorage(data), reqVars, diff --git a/ers/filexml.go b/ers/filexml.go index 8527f5dee..01be446fa 100644 --- a/ers/filexml.go +++ b/ers/filexml.go @@ -138,7 +138,7 @@ func (rdr *XMLFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := utils.NavigableMap{utils.FileName: utils.NewNMData(fName)} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} for _, xmlElmt := range xmlElmts { rowNr++ // increment the rowNr after checking if it's not the end of file agReq := agents.NewAgentRequest( diff --git a/ers/flatstore.go b/ers/flatstore.go index 55101ccf5..cdf5c58ff 100644 --- a/ers/flatstore.go +++ b/ers/flatstore.go @@ -147,7 +147,7 @@ func (rdr *FlatstoreER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := utils.NavigableMap{utils.FileName: utils.NewNMData(fName)} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} for { var record []string if record, err = csvReader.Read(); err != nil { diff --git a/ers/partial_csv.go b/ers/partial_csv.go index 026870fff..3111c8ca6 100644 --- a/ers/partial_csv.go +++ b/ers/partial_csv.go @@ -155,7 +155,7 @@ func (rdr *PartialCSVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := utils.NavigableMap{utils.FileName: utils.NewNMData(fName)} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} for { var record []string if record, err = csvReader.Read(); err != nil { diff --git a/go.sum b/go.sum index 80a4c0bdf..911fd6202 100644 --- a/go.sum +++ b/go.sum @@ -9,12 +9,10 @@ cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6T cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.75.0 h1:XgtDnVJRCPEUG21gjFiRPz4zI1Mjg16R+NYQjfmU4XY= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= @@ -40,13 +38,11 @@ github.com/Azure/go-amqp v0.13.1 h1:dXnEJ89Hf7wMkcBbLqvocZlM4a3uiX9uCxJIvU77+Oo= github.com/Azure/go-amqp v0.13.1/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/RoaringBitmap/roaring v0.4.23 h1:gpyfd12QohbqhFO4NVDUdoPOCXsyahYRQhINmlHxKeo= github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= github.com/RoaringBitmap/roaring v0.5.5 h1:naNqvO1mNnghk2UvcsqnzHDBn9DRbCIRy94GmDTRVTQ= github.com/RoaringBitmap/roaring v0.5.5/go.mod h1:puNo5VdzwbaIQxSiDIwfXl4Hnc+fbovcX4IW/dSTtUk= github.com/antchfx/xmlquery v1.3.3 h1:HYmadPG0uz8CySdL68rB4DCLKXz2PurCjS3mnkVF4CQ= github.com/antchfx/xmlquery v1.3.3/go.mod h1:64w0Xesg2sTaawIdNqMB+7qaW/bSqkQm+ssPaCMWNnc= -github.com/antchfx/xpath v1.1.10 h1:cJ0pOvEdN/WvYXxvRrzQH9x5QWKpzHacYO8qzCcDYAg= github.com/antchfx/xpath v1.1.10/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= github.com/antchfx/xpath v1.1.11 h1:WOFtK8TVAjLm3lbgqeP0arlHpvCEeTANeWZ/csPpJkQ= github.com/antchfx/xpath v1.1.11/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= @@ -82,7 +78,6 @@ github.com/cenk/hub v1.0.1 h1:RBwXNOF4a8KjD8BJ08XqN8KbrqaGiQLDrgvUGJSHuPA= github.com/cenk/hub v1.0.1/go.mod h1:rJM1LNAW0ppT8FMMuPK6c2NP/R2nH/UthtuRySSaf6Y= github.com/cenkalti/hub v1.0.1 h1:UMtjc6dHSaOQTO15SVA50MBIR9zQwvsukQupDrkIRtg= github.com/cenkalti/hub v1.0.1/go.mod h1:tcYwtS3a2d9NO/0xDXVJWx3IedurUjYCqFCmpi0lpHs= -github.com/cenkalti/rpc2 v0.0.0-20210117202628-1bea588996c7 h1:FzmeDLoHQVNEXiH4MY6YtGu+l3oC6D70I2IVFDsNMTQ= github.com/cenkalti/rpc2 v0.0.0-20210117202628-1bea588996c7/go.mod h1:v2npkhrXyk5BCnkNIiPdRI23Uq6uWPUQGL2hnRcRr/M= github.com/cenkalti/rpc2 v0.0.0-20210220005819-4a29bc83afe1 h1:aT9Ez2drLmrviqTnVnH87AeXLXLgUrXACJ2g90cTT2w= github.com/cenkalti/rpc2 v0.0.0-20210220005819-4a29bc83afe1/go.mod h1:v2npkhrXyk5BCnkNIiPdRI23Uq6uWPUQGL2hnRcRr/M= @@ -132,9 +127,7 @@ github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8= github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= -github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso= github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= -github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 h1:MZRmHqDBd0vxNwenEbKSQqRVT24d3C05ft8kduSwlqM= github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -152,11 +145,8 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ericlagergren/decimal v0.0.0-20191206042408-88212e6cfca9 h1:mMVotm9OVwoOS2IFGRRS5AfMTFWhtf8wj34JEYh47/k= github.com/ericlagergren/decimal v0.0.0-20191206042408-88212e6cfca9/go.mod h1:ZWP59etEywfyMG2lAqnoi3t8uoiZCiTmLtwt6iESIsQ= -github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= -github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fiorix/go-diameter/v4 v4.0.2 h1:JVxecvfWqqvZWVO6PLTwUj/CV7CusaqYtz40WNYfWvI= github.com/fiorix/go-diameter/v4 v4.0.2/go.mod h1:Qx/+pf+c9sBUHWq1d7EH3bkdwN8U0mUpdy9BieDw6UQ= @@ -167,7 +157,6 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 h1:Ujru1hufTHVb++eG6OuNDKMxZnGIvF6o/u8q/8h2+I4= github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a h1:FQqoVvjbiUioBBFUL5up+h+GdCa/AnJsL/1bIs/veSI= github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= @@ -223,7 +212,6 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -231,12 +219,10 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -245,10 +231,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -361,14 +345,12 @@ github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaR github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.9.8 h1:VMAMUUOh+gaxKTMk+zqbjsSjsIcUcL/LF4o63i82QyA= github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.6 h1:EgWPCW6O3n1D5n99Zq3xXBt9uCwRGvpwGOusOLNBRSQ= github.com/klauspost/compress v1.11.6/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -421,13 +403,10 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/peterh/liner v1.2.1 h1:O4BlKaq/LWu6VRWmol4ByWfzx6MfXc5Op5HETyIy5yg= github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= -github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/philhofer/fwd v1.1.0 h1:PAdZw9+/BCf4gc/kA2L/PbGPkFe72Kl2GLZXTG8HpU8= github.com/philhofer/fwd v1.1.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A= github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -441,9 +420,7 @@ github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74 github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -480,7 +457,6 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -492,14 +468,11 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7 github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.5 h1:2gXmtWueD2HefZHQe1QOy9HVzmFrLOVvsXwXBQ0ayy0= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 h1:3SVOIvH7Ae1KRYyQWRjXWJEA9sS/c/pjvH++55Gr648= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= @@ -522,7 +495,6 @@ go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4S go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= @@ -549,7 +521,6 @@ golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200320181102-891825fb96df/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= @@ -574,9 +545,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -585,9 +554,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -623,7 +590,6 @@ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -631,10 +597,8 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 h1:Mj83v+wSRNEar42a/MQgxk9X42TdEmrOl9i+y8WbxLo= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -645,10 +609,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -686,7 +648,6 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -694,7 +655,6 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -706,9 +666,7 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -768,14 +726,12 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a h1:+77BOOi9CMFjpy3D2P/OnfSSmC/Hx/fGAQJUAQaM2gc= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -793,7 +749,6 @@ google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= @@ -803,7 +758,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -828,12 +782,10 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -841,7 +793,6 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e h1:wYR00/Ht+i/79g/gzhdehBgLIJCklKoc8Q/NebdzzpY= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210111234610-22ae2b108f89 h1:R2owLnwrU3BdTJ5R9cnHDNsnEmBQ7n5lZjKShnbISe4= @@ -855,13 +806,11 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.34.1 h1:ugq+9++ZQPFzM2pKUMCIK8gj9M0pFyuUWO9Q8kwEDQw= @@ -872,14 +821,12 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= @@ -889,7 +836,6 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/utils/datanode.go b/utils/datanode.go index 085582bd5..39e23821f 100644 --- a/utils/datanode.go +++ b/utils/datanode.go @@ -36,9 +36,7 @@ func CompilePathSlice(spath []string) (path []string) { continue } path = append(path, p[:idxStart]) - if idxVal := p[idxStart+1 : len(p)-1]; strings.Index(idxVal, IdxCombination) != -1 { - path = append(path, strings.Split(idxVal, IdxCombination)...) - } + path = append(path, strings.Split(p[idxStart+1:len(p)-1], IdxCombination)...) } return } @@ -62,12 +60,34 @@ func NewDataNode(path []string) (n *DataNode) { return } +func NewLeafNode(val interface{}) *DataNode { + return &DataNode{ + Type: NMDataType, + Value: &DataLeaf{ + Data: val, + }, + } +} + // DataNode a structure for storing data type DataNode struct { Type NMType `json:"-"` Map map[string]*DataNode `json:",omitempty"` Slice []*DataNode `json:",omitempty"` - Value interface{} `json:",omitempty"` + Value *DataLeaf `json:",omitempty"` +} + +// DataLeaf is an item in the DataNode +type DataLeaf struct { + Data interface{} // value of the element + Path []string // path in map + NewBranch bool + AttributeID string + // Config *FCTemplate // so we can store additional configuration +} + +func (dl *DataLeaf) String() string { + return IfaceAsString(dl.Data) } // Field returns the value found at path @@ -75,7 +95,7 @@ type DataNode struct { // field1[field2][index].field3 // should be of following form: // field1.field2.index.field3 -func (n *DataNode) Field(path []string) (interface{}, error) { +func (n *DataNode) Field(path []string) (*DataLeaf, error) { switch n.Type { // based on current type return the value case NMDataType: if len(path) != 0 { // only return if the path is empty @@ -84,7 +104,7 @@ func (n *DataNode) Field(path []string) (interface{}, error) { return n.Value, nil case NMMapType: if len(path) == 0 { - return n.Map, nil + return nil, ErrWrongPath } node, has := n.Map[path[0]] if !has { @@ -93,7 +113,7 @@ func (n *DataNode) Field(path []string) (interface{}, error) { return node.Field(path[1:]) // let the next node handle the value case NMSliceType: if len(path) == 0 { - return n.Slice, nil + return nil, ErrWrongPath } idx, err := strconv.Atoi(path[0]) // convert the path to index if err != nil { @@ -111,6 +131,45 @@ func (n *DataNode) Field(path []string) (interface{}, error) { return nil, ErrWrongPath } +func (n *DataNode) FieldAsInterface(path []string) (interface{}, error) { + return n.fieldAsInterface(CompilePathSlice(path)) +} +func (n *DataNode) fieldAsInterface(path []string) (interface{}, error) { + switch n.Type { // based on current type return the value + case NMDataType: + if len(path) != 0 { // only return if the path is empty + return nil, ErrNotFound + } + return n.Value.Data, nil + case NMMapType: + if len(path) == 0 { + return n.Map, nil + } + node, has := n.Map[path[0]] + if !has { + return nil, ErrNotFound + } + return node.fieldAsInterface(path[1:]) // let the next node handle the value + case NMSliceType: + if len(path) == 0 { + return n.Slice, nil + } + idx, err := strconv.Atoi(path[0]) // convert the path to index + if err != nil { + return nil, err + } + if idx < 0 { // in case the index is negative add the slice lenght + idx += len(n.Slice) + } + if idx < 0 || idx >= len(n.Slice) { // check if the index is in range [0,len(slice)) + return nil, ErrNotFound + } + return n.Slice[idx].fieldAsInterface(path[1:]) + } + // this is possible if the node was created but no value was assigned to it + return nil, ErrWrongPath +} + // Set will set the value at de specified path // the path should be in the same format as the path given to Field func (n *DataNode) Set(path []string, val interface{}) (addedNew bool, err error) { @@ -119,14 +178,22 @@ func (n *DataNode) Set(path []string, val interface{}) (addedNew bool, err error case map[string]*DataNode: n.Type = NMMapType n.Map = v - addedNew = true case []*DataNode: n.Type = NMSliceType n.Slice = v - addedNew = true + case *DataLeaf: + n.Type = NMDataType + n.Value = v + case *DataNode: + n.Type = v.Type + n.Map = v.Map + n.Slice = v.Slice + n.Value = v.Value default: n.Type = NMDataType - n.Value = val + n.Value = &DataLeaf{ + Data: val, + } } return } @@ -219,15 +286,25 @@ func (n *DataNode) Remove(path []string) error { // Append will append the value at de specified path // the path should be in the same format as the path given to Field -func (n *DataNode) Append(path []string, val interface{}) (idx int, err error) { +func (n *DataNode) Append(path []string, val *DataLeaf) (idx int, err error) { if len(path) == 0 { // the path is empty so overwrite curent node data - if n.Type == NMDataType || - n.Type == NMMapType { + switch n.Type { + case NMMapType: return -1, ErrWrongPath + case NMDataType: + if n.Value != nil && n.Value.Data != nil { + return -1, ErrWrongPath + } + // is empty so make a slice to be compatible with append + n.Type = NMSliceType + n.Value = nil + n.Slice = []*DataNode{{Type: NMDataType, Value: val}} + return 0, nil + default: + n.Type = NMSliceType + n.Slice = append(n.Slice, &DataNode{Type: NMDataType, Value: val}) + return len(n.Slice) - 1, nil } - n.Type = NMSliceType - n.Slice = append(n.Slice, &DataNode{Type: NMDataType, Value: val}) - return len(n.Slice) - 1, nil } switch n.Type { case NMDataType: @@ -264,18 +341,28 @@ func (n *DataNode) Append(path []string, val interface{}) (idx int, err error) { // Compose will set the value at de specified path // the path should be in the same format as the path given to Field -func (n *DataNode) Compose(path []string, val interface{}) (err error) { +func (n *DataNode) Compose(path []string, val *DataLeaf) (err error) { if len(path) == 0 { // the path is empty so overwrite curent node data - if n.Type == NMDataType || - n.Type == NMMapType { + switch n.Type { + case NMMapType: return ErrWrongPath + case NMDataType: + if n.Value == nil || n.Value.Data == nil { + // is empty so make a slice to be compatible with append + n.Type = NMSliceType + n.Value = nil + n.Slice = []*DataNode{{Type: NMDataType, Value: val}} + return + } + n.Value.Data = n.Value.String() + val.String() + default: + if len(n.Slice) == 0 { + n.Type = NMSliceType + n.Slice = []*DataNode{{Type: NMDataType, Value: val}} + return + } + n.Slice[len(n.Slice)-1].Value.Data = n.Slice[len(n.Slice)-1].Value.String() + val.String() } - if len(n.Slice) == 0 { - n.Type = NMSliceType - n.Slice = []*DataNode{{Type: NMDataType, Value: val}} - return - } - n.Slice[len(n.Slice)-1].Value = IfaceAsString(n.Slice[len(n.Slice)-1].Value) + IfaceAsString(val) return } switch n.Type { diff --git a/utils/dataprovider.go b/utils/dataprovider.go index 8538b3219..82cbc9bd3 100644 --- a/utils/dataprovider.go +++ b/utils/dataprovider.go @@ -51,7 +51,7 @@ type RWDataProvider interface { // NavigableMapper is the interface supported by replies convertible to CGRReply type NavigableMapper interface { - AsNavigableMap() *DataNode + AsNavigableMap() map[string]*DataNode } // DPDynamicInterface returns the value of the field if the path is dynamic diff --git a/utils/orderednavigablemap.go b/utils/orderednavigablemap.go index 20e42b1ba..670f8cf33 100644 --- a/utils/orderednavigablemap.go +++ b/utils/orderednavigablemap.go @@ -56,7 +56,7 @@ func (onm *OrderedNavigableMap) Interface() interface{} { } // Field returns the item on the given path -func (onm *OrderedNavigableMap) Field(fldPath []string) (val interface{}, err error) { +func (onm *OrderedNavigableMap) Field(fldPath []string) (val *DataLeaf, err error) { return onm.nm.Field(fldPath) } @@ -70,6 +70,7 @@ func (onm *OrderedNavigableMap) Remove(fullPath *FullPath) (err error) { if fullPath.Path == EmptyString { return ErrWrongPath } + fullPath.PathItems = CloneSlice(fullPath.PathItems) if err = onm.nm.Remove(fullPath.PathItems); err != nil { return } @@ -131,7 +132,7 @@ func (onm *OrderedNavigableMap) SetAsSlice(fullPath *FullPath, vals []*DataNode) pathItmsSet := make([][]string, len(vals)) for i := range vals { - pathItms := append([]string{}, fullPath.PathItems...) + pathItms := CloneSlice(fullPath.PathItems) pathItms = append(pathItms, strconv.Itoa(i)) pathItmsSet[i] = pathItms } @@ -170,7 +171,7 @@ func (onm *OrderedNavigableMap) FieldAsString(fldPath []string) (str string, err // FieldAsInterface returns the interface at the path func (onm *OrderedNavigableMap) FieldAsInterface(fldPath []string) (iface interface{}, err error) { - return onm.nm.Field(CompilePathSlice(fldPath)) + return onm.nm.FieldAsInterface(fldPath) } // RemoteHost is part of dataStorage interface @@ -215,7 +216,7 @@ func (onm *OrderedNavigableMap) OrderedFieldsAsStrings() (flds []string) { // Set sets the value at the given path // this used with full path and the processed path to not calculate them for every set -func (onm *OrderedNavigableMap) Append(fullPath *FullPath, val interface{}) (err error) { +func (onm *OrderedNavigableMap) Append(fullPath *FullPath, val *DataLeaf) (err error) { if fullPath == nil || len(fullPath.PathItems) == 0 { return ErrWrongPath } @@ -230,7 +231,7 @@ func (onm *OrderedNavigableMap) Append(fullPath *FullPath, val interface{}) (err // Set sets the value at the given path // this used with full path and the processed path to not calculate them for every set -func (onm *OrderedNavigableMap) Compose(fullPath *FullPath, val interface{}) (err error) { +func (onm *OrderedNavigableMap) Compose(fullPath *FullPath, val *DataLeaf) (err error) { if fullPath == nil || len(fullPath.PathItems) == 0 { return ErrWrongPath } diff --git a/utils/slice.go b/utils/slice.go index cdc716bb4..070c2066b 100644 --- a/utils/slice.go +++ b/utils/slice.go @@ -70,3 +70,11 @@ func HasPrefixSlice(prfxs []string, el string) bool { } return false } + +func CloneSlice(in []string) (cl []string) { + cl = make([]string, len(in)) + for i, j := range in { + cl[i] = j + } + return +}