mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 18:46:24 +05:00
cfg: add stats/thresholds_conns to radius_agent
This commit is contained in:
committed by
Dan Christian Bogos
parent
d71327a00e
commit
f95273db30
@@ -1048,6 +1048,8 @@ const CGRATES_CFG_JSON = `
|
||||
"*default": "/usr/share/cgrates/radius/dict/", // key represents the client IP or catch-all <*default|$client_ip>
|
||||
},
|
||||
"sessions_conns": ["*internal"],
|
||||
"stats_conns": [], // connections to StatS, empty to disable: <""|*internal|$rpc_conns_id>
|
||||
"thresholds_conns": [], // connections to ThresholdS, empty to disable: <""|*internal|$rpc_conns_id>
|
||||
"request_processors": [] // request processors to be applied to Radius messages
|
||||
},
|
||||
|
||||
|
||||
@@ -761,18 +761,20 @@ func TestDiameterAgentJsonCfg(t *testing.T) {
|
||||
|
||||
func TestRadiusAgentJsonCfg(t *testing.T) {
|
||||
eCfg := &RadiusAgentJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
Listen_net: utils.StringPointer("udp"),
|
||||
Listen_auth: utils.StringPointer("127.0.0.1:1812"),
|
||||
Listen_acct: utils.StringPointer("127.0.0.1:1813"),
|
||||
Client_secrets: map[string]string{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
ListenNet: utils.StringPointer("udp"),
|
||||
ListenAuth: utils.StringPointer("127.0.0.1:1812"),
|
||||
ListenAcct: utils.StringPointer("127.0.0.1:1813"),
|
||||
ClientSecrets: map[string]string{
|
||||
utils.MetaDefault: "CGRateS.org",
|
||||
},
|
||||
Client_dictionaries: map[string]string{
|
||||
ClientDictionaries: map[string]string{
|
||||
utils.MetaDefault: "/usr/share/cgrates/radius/dict/",
|
||||
},
|
||||
Sessions_conns: &[]string{utils.MetaInternal},
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{},
|
||||
SessionSConns: &[]string{utils.MetaInternal},
|
||||
StatSConns: &[]string{},
|
||||
ThresholdSConns: &[]string{},
|
||||
RequestProcessors: &[]*ReqProcessorJsnCfg{},
|
||||
}
|
||||
dfCgrJSONCfg, err := NewCgrJsonCfgFromBytes([]byte(CGRATES_CFG_JSON))
|
||||
if err != nil {
|
||||
@@ -782,8 +784,8 @@ func TestRadiusAgentJsonCfg(t *testing.T) {
|
||||
if err := dfCgrJSONCfg.GetSection(context.Background(), RadiusAgentJSON, cfg); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCfg, cfg) {
|
||||
rcv := *cfg.Request_processors
|
||||
t.Errorf("Received: %+v", rcv)
|
||||
rcv := *cfg.RequestProcessors
|
||||
t.Errorf("Received: %+v", utils.ToJSON(rcv))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -375,6 +375,22 @@ func (cfg *CGRConfig) checkConfigSanity() error {
|
||||
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.RadiusAgent, connID)
|
||||
}
|
||||
}
|
||||
for _, connID := range cfg.radiusAgentCfg.StatSConns {
|
||||
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.statsCfg.Enabled {
|
||||
return fmt.Errorf("<%s> not enabled but requested by <%s> component", utils.StatS, utils.RadiusAgent)
|
||||
}
|
||||
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
||||
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.RadiusAgent, connID)
|
||||
}
|
||||
}
|
||||
for _, connID := range cfg.radiusAgentCfg.ThresholdSConns {
|
||||
if strings.HasPrefix(connID, utils.MetaInternal) && !cfg.thresholdSCfg.Enabled {
|
||||
return fmt.Errorf("<%s> not enabled but requested by <%s> component", utils.ThresholdS, utils.RadiusAgent)
|
||||
}
|
||||
if _, has := cfg.rpcConns[connID]; !has && !strings.HasPrefix(connID, utils.MetaInternal) {
|
||||
return fmt.Errorf("<%s> connection with id: <%s> not defined", utils.RadiusAgent, connID)
|
||||
}
|
||||
}
|
||||
for _, req := range cfg.radiusAgentCfg.RequestProcessors {
|
||||
for _, field := range req.RequestFields {
|
||||
if field.Type != utils.MetaNone && field.Path == utils.EmptyString {
|
||||
|
||||
200
config/radius.go
Normal file
200
config/radius.go
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"maps"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// RadiusAgentCfg the config section that describes the Radius Agent
|
||||
type RadiusAgentCfg struct {
|
||||
Enabled bool
|
||||
ListenNet string // udp or tcp
|
||||
ListenAuth string
|
||||
ListenAcct string
|
||||
ClientSecrets map[string]string
|
||||
ClientDictionaries map[string]string
|
||||
SessionSConns []string
|
||||
StatSConns []string
|
||||
ThresholdSConns []string
|
||||
RequestProcessors []*RequestProcessor
|
||||
}
|
||||
|
||||
// loadRadiusAgentCfg loads the RadiusAgent section of the configuration
|
||||
func (ra *RadiusAgentCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig) (err error) {
|
||||
jsnRACfg := new(RadiusAgentJsonCfg)
|
||||
if err = jsnCfg.GetSection(ctx, RadiusAgentJSON, jsnRACfg); err != nil {
|
||||
return
|
||||
}
|
||||
return ra.loadFromJSONCfg(jsnRACfg)
|
||||
}
|
||||
|
||||
func (ra *RadiusAgentCfg) loadFromJSONCfg(jsnCfg *RadiusAgentJsonCfg) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
ra.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.ListenNet != nil {
|
||||
ra.ListenNet = *jsnCfg.ListenNet
|
||||
}
|
||||
if jsnCfg.ListenAuth != nil {
|
||||
ra.ListenAuth = *jsnCfg.ListenAuth
|
||||
}
|
||||
if jsnCfg.ListenAcct != nil {
|
||||
ra.ListenAcct = *jsnCfg.ListenAcct
|
||||
}
|
||||
maps.Copy(ra.ClientSecrets, jsnCfg.ClientSecrets)
|
||||
maps.Copy(ra.ClientDictionaries, jsnCfg.ClientDictionaries)
|
||||
if jsnCfg.SessionSConns != nil {
|
||||
ra.SessionSConns = tagInternalConns(*jsnCfg.SessionSConns, utils.MetaSessionS)
|
||||
}
|
||||
if jsnCfg.StatSConns != nil {
|
||||
ra.StatSConns = tagInternalConns(*jsnCfg.StatSConns, utils.MetaStats)
|
||||
}
|
||||
if jsnCfg.ThresholdSConns != nil {
|
||||
ra.ThresholdSConns = tagInternalConns(*jsnCfg.ThresholdSConns, utils.MetaThresholds)
|
||||
}
|
||||
ra.RequestProcessors, err = appendRequestProcessors(ra.RequestProcessors, jsnCfg.RequestProcessors)
|
||||
return
|
||||
}
|
||||
|
||||
// AsMapInterface returns the config as a map[string]any
|
||||
func (ra RadiusAgentCfg) AsMapInterface() any {
|
||||
requestProcessors := make([]map[string]any, len(ra.RequestProcessors))
|
||||
for i, item := range ra.RequestProcessors {
|
||||
requestProcessors[i] = item.AsMapInterface()
|
||||
}
|
||||
mp := map[string]any{
|
||||
utils.EnabledCfg: ra.Enabled,
|
||||
utils.ListenNetCfg: ra.ListenNet,
|
||||
utils.ListenAuthCfg: ra.ListenAuth,
|
||||
utils.ListenAcctCfg: ra.ListenAcct,
|
||||
utils.ClientSecretsCfg: maps.Clone(ra.ClientSecrets),
|
||||
utils.ClientDictionariesCfg: maps.Clone(ra.ClientDictionaries),
|
||||
utils.SessionSConnsCfg: stripInternalConns(ra.SessionSConns),
|
||||
utils.StatSConnsCfg: stripInternalConns(ra.StatSConns),
|
||||
utils.ThresholdSConnsCfg: stripInternalConns(ra.ThresholdSConns),
|
||||
utils.RequestProcessorsCfg: requestProcessors,
|
||||
}
|
||||
return mp
|
||||
}
|
||||
|
||||
func (RadiusAgentCfg) SName() string { return RadiusAgentJSON }
|
||||
func (ra RadiusAgentCfg) CloneSection() Section { return ra.Clone() }
|
||||
|
||||
// Clone returns a deep copy of RadiusAgentCfg
|
||||
func (ra RadiusAgentCfg) Clone() *RadiusAgentCfg {
|
||||
clone := &RadiusAgentCfg{
|
||||
Enabled: ra.Enabled,
|
||||
ListenNet: ra.ListenNet,
|
||||
ListenAuth: ra.ListenAuth,
|
||||
ListenAcct: ra.ListenAcct,
|
||||
ClientSecrets: maps.Clone(ra.ClientSecrets),
|
||||
|
||||
// NOTE: shallow clone and value is a slice
|
||||
ClientDictionaries: maps.Clone(ra.ClientDictionaries),
|
||||
|
||||
SessionSConns: slices.Clone(ra.SessionSConns),
|
||||
StatSConns: slices.Clone(ra.StatSConns),
|
||||
ThresholdSConns: slices.Clone(ra.ThresholdSConns),
|
||||
}
|
||||
if ra.RequestProcessors != nil {
|
||||
clone.RequestProcessors = make([]*RequestProcessor, len(ra.RequestProcessors))
|
||||
for i, req := range ra.RequestProcessors {
|
||||
clone.RequestProcessors[i] = req.Clone()
|
||||
}
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
// Radius Agent configuration section
|
||||
type RadiusAgentJsonCfg struct {
|
||||
Enabled *bool `json:"enabled"`
|
||||
ListenNet *string `json:"listen_net"`
|
||||
ListenAuth *string `json:"listen_auth"`
|
||||
ListenAcct *string `json:"listen_acct"`
|
||||
ClientSecrets map[string]string `json:"client_secrets"`
|
||||
ClientDictionaries map[string]string `json:"client_dictionaries"`
|
||||
SessionSConns *[]string `json:"sessions_conns"`
|
||||
StatSConns *[]string `json:"stats_conns"`
|
||||
ThresholdSConns *[]string `json:"thresholds_conns"`
|
||||
RequestProcessors *[]*ReqProcessorJsnCfg `json:"request_processors"`
|
||||
}
|
||||
|
||||
func diffRadiusAgentJsonCfg(d *RadiusAgentJsonCfg, v1, v2 *RadiusAgentCfg) *RadiusAgentJsonCfg {
|
||||
if d == nil {
|
||||
d = new(RadiusAgentJsonCfg)
|
||||
}
|
||||
if v1.Enabled != v2.Enabled {
|
||||
d.Enabled = utils.BoolPointer(v2.Enabled)
|
||||
}
|
||||
if v1.ListenNet != v2.ListenNet {
|
||||
d.ListenNet = utils.StringPointer(v2.ListenNet)
|
||||
}
|
||||
if v1.ListenAuth != v2.ListenAuth {
|
||||
d.ListenAuth = utils.StringPointer(v2.ListenAuth)
|
||||
}
|
||||
if v1.ListenAcct != v2.ListenAcct {
|
||||
d.ListenAcct = utils.StringPointer(v2.ListenAcct)
|
||||
}
|
||||
d.ClientSecrets = diffMapString(d.ClientSecrets, v1.ClientSecrets, v2.ClientSecrets)
|
||||
d.ClientDictionaries = diffMapString(d.ClientDictionaries, v1.ClientDictionaries, v2.ClientDictionaries)
|
||||
if !slices.Equal(v1.SessionSConns, v2.SessionSConns) {
|
||||
d.SessionSConns = utils.SliceStringPointer(stripInternalConns(v2.SessionSConns))
|
||||
}
|
||||
if !slices.Equal(v1.StatSConns, v2.StatSConns) {
|
||||
d.StatSConns = utils.SliceStringPointer(stripInternalConns(v2.StatSConns))
|
||||
}
|
||||
if !slices.Equal(v1.ThresholdSConns, v2.ThresholdSConns) {
|
||||
d.ThresholdSConns = utils.SliceStringPointer(stripInternalConns(v2.ThresholdSConns))
|
||||
}
|
||||
d.RequestProcessors = diffReqProcessorsJsnCfg(d.RequestProcessors, v1.RequestProcessors, v2.RequestProcessors)
|
||||
return d
|
||||
}
|
||||
|
||||
func diffMapString(d, v1, v2 map[string]string) map[string]string {
|
||||
if d == nil {
|
||||
d = make(map[string]string)
|
||||
}
|
||||
for k, v := range v2 {
|
||||
if val, has := v1[k]; !has || val != v {
|
||||
d[k] = v
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func diffMapStringSlice(d, v1, v2 map[string][]string) map[string][]string {
|
||||
if d == nil {
|
||||
d = make(map[string][]string)
|
||||
}
|
||||
for k, v := range v2 {
|
||||
if val, has := v1[k]; !has || !slices.Equal(val, v) {
|
||||
d[k] = v
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
@@ -28,14 +28,16 @@ import (
|
||||
|
||||
func TestRadiusAgentCfgloadFromJsonCfgCase1(t *testing.T) {
|
||||
cfgJSON := &RadiusAgentJsonCfg{
|
||||
Enabled: utils.BoolPointer(true),
|
||||
Listen_net: utils.StringPointer(utils.UDP),
|
||||
Listen_auth: utils.StringPointer("127.0.0.1:1812"),
|
||||
Listen_acct: utils.StringPointer("127.0.0.1:1813"),
|
||||
Client_secrets: map[string]string{utils.MetaDefault: "CGRateS.org"},
|
||||
Client_dictionaries: map[string]string{utils.MetaDefault: "/usr/share/cgrates/radius/dict/"},
|
||||
Sessions_conns: &[]string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaSessionS)},
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{
|
||||
Enabled: utils.BoolPointer(true),
|
||||
ListenNet: utils.StringPointer(utils.UDP),
|
||||
ListenAuth: utils.StringPointer("127.0.0.1:1812"),
|
||||
ListenAcct: utils.StringPointer("127.0.0.1:1813"),
|
||||
ClientSecrets: map[string]string{utils.MetaDefault: "CGRateS.org"},
|
||||
ClientDictionaries: map[string]string{utils.MetaDefault: "/usr/share/cgrates/radius/dict/"},
|
||||
SessionSConns: &[]string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaSessionS)},
|
||||
StatSConns: &[]string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)},
|
||||
ThresholdSConns: &[]string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds)},
|
||||
RequestProcessors: &[]*ReqProcessorJsnCfg{
|
||||
{
|
||||
ID: utils.StringPointer("OutboundAUTHDryRun"),
|
||||
Filters: &[]string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"},
|
||||
@@ -64,6 +66,8 @@ func TestRadiusAgentCfgloadFromJsonCfgCase1(t *testing.T) {
|
||||
ClientSecrets: map[string]string{utils.MetaDefault: "CGRateS.org"},
|
||||
ClientDictionaries: map[string]string{utils.MetaDefault: "/usr/share/cgrates/radius/dict/"},
|
||||
SessionSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaSessionS)},
|
||||
StatSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)},
|
||||
ThresholdSConns: []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds)},
|
||||
RequestProcessors: []*RequestProcessor{
|
||||
{
|
||||
ID: "OutboundAUTHDryRun",
|
||||
@@ -111,7 +115,7 @@ func TestRadiusAgentCfgloadFromJsonCfgCase2(t *testing.T) {
|
||||
},
|
||||
}`
|
||||
cfgJSON := &RadiusAgentJsonCfg{
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{
|
||||
RequestProcessors: &[]*ReqProcessorJsnCfg{
|
||||
{
|
||||
ID: utils.StringPointer("OutboundAUTHDryRun"),
|
||||
},
|
||||
@@ -136,7 +140,7 @@ func TestRadiusAgentCfgloadFromJsonCfgCase2(t *testing.T) {
|
||||
|
||||
func TestRadiusAgentCfgloadFromJsonCfgCase3(t *testing.T) {
|
||||
cfgJSON := &RadiusAgentJsonCfg{
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{
|
||||
RequestProcessors: &[]*ReqProcessorJsnCfg{
|
||||
{
|
||||
Tenant: utils.StringPointer("a{*"),
|
||||
},
|
||||
@@ -160,6 +164,8 @@ func TestRadiusAgentCfgAsMapInterface(t *testing.T) {
|
||||
"*default": "/usr/share/cgrates/",
|
||||
},
|
||||
"sessions_conns": ["*birpc_internal", "*conn1","*conn2"],
|
||||
"stats_conns": ["*internal", "*conn1","*conn2"],
|
||||
"thresholds_conns": ["*internal", "*conn1","*conn2"],
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "OutboundAUTHDryRun",
|
||||
@@ -185,7 +191,9 @@ func TestRadiusAgentCfgAsMapInterface(t *testing.T) {
|
||||
utils.ClientDictionariesCfg: map[string]string{
|
||||
utils.MetaDefault: "/usr/share/cgrates/",
|
||||
},
|
||||
utils.SessionSConnsCfg: []string{rpcclient.BiRPCInternal, "*conn1", "*conn2"},
|
||||
utils.SessionSConnsCfg: []string{rpcclient.BiRPCInternal, "*conn1", "*conn2"},
|
||||
utils.StatSConnsCfg: []string{utils.MetaInternal, "*conn1", "*conn2"},
|
||||
utils.ThresholdSConnsCfg: []string{utils.MetaInternal, "*conn1", "*conn2"},
|
||||
utils.RequestProcessorsCfg: []map[string]any{
|
||||
{
|
||||
utils.IDCfg: "OutboundAUTHDryRun",
|
||||
@@ -223,6 +231,8 @@ func TestRadiusAgentCfgAsMapInterface1(t *testing.T) {
|
||||
utils.MetaDefault: "/usr/share/cgrates/radius/dict/",
|
||||
},
|
||||
utils.SessionSConnsCfg: []string{"*internal"},
|
||||
utils.StatSConnsCfg: []string{},
|
||||
utils.ThresholdSConnsCfg: []string{},
|
||||
utils.RequestProcessorsCfg: []map[string]any{},
|
||||
}
|
||||
if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil {
|
||||
@@ -291,6 +301,8 @@ func TestDiffRadiusAgentJsonCfg(t *testing.T) {
|
||||
ClientSecrets: map[string]string{},
|
||||
ClientDictionaries: map[string]string{},
|
||||
SessionSConns: []string{"*localhost"},
|
||||
StatSConns: []string{"*localhost"},
|
||||
ThresholdSConns: []string{"*localhost"},
|
||||
RequestProcessors: []*RequestProcessor{},
|
||||
}
|
||||
|
||||
@@ -305,7 +317,9 @@ func TestDiffRadiusAgentJsonCfg(t *testing.T) {
|
||||
ClientDictionaries: map[string]string{
|
||||
"radius_dict1": "radius_val1",
|
||||
},
|
||||
SessionSConns: []string{"*birpc"},
|
||||
SessionSConns: []string{"*internal"},
|
||||
StatSConns: []string{"*internal"},
|
||||
ThresholdSConns: []string{"*internal"},
|
||||
RequestProcessors: []*RequestProcessor{
|
||||
{
|
||||
ID: "REQ_PROC1",
|
||||
@@ -315,18 +329,20 @@ func TestDiffRadiusAgentJsonCfg(t *testing.T) {
|
||||
}
|
||||
|
||||
expected := &RadiusAgentJsonCfg{
|
||||
Enabled: utils.BoolPointer(true),
|
||||
Listen_net: utils.StringPointer("udp"),
|
||||
Listen_auth: utils.StringPointer("radius_auth2"),
|
||||
Listen_acct: utils.StringPointer("radius_account2"),
|
||||
Client_secrets: map[string]string{
|
||||
Enabled: utils.BoolPointer(true),
|
||||
ListenNet: utils.StringPointer("udp"),
|
||||
ListenAuth: utils.StringPointer("radius_auth2"),
|
||||
ListenAcct: utils.StringPointer("radius_account2"),
|
||||
ClientSecrets: map[string]string{
|
||||
"radius_user": "radius_pass",
|
||||
},
|
||||
Client_dictionaries: map[string]string{
|
||||
ClientDictionaries: map[string]string{
|
||||
"radius_dict1": "radius_val1",
|
||||
},
|
||||
Sessions_conns: &[]string{"*birpc"},
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{
|
||||
SessionSConns: &[]string{"*internal"},
|
||||
StatSConns: &[]string{"*internal"},
|
||||
ThresholdSConns: &[]string{"*internal"},
|
||||
RequestProcessors: &[]*ReqProcessorJsnCfg{
|
||||
{
|
||||
ID: utils.StringPointer("REQ_PROC1"),
|
||||
Filters: &[]string{"filter1"},
|
||||
@@ -341,9 +357,9 @@ func TestDiffRadiusAgentJsonCfg(t *testing.T) {
|
||||
|
||||
v1 = v2
|
||||
expected = &RadiusAgentJsonCfg{
|
||||
Client_secrets: map[string]string{},
|
||||
Client_dictionaries: map[string]string{},
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{
|
||||
ClientSecrets: map[string]string{},
|
||||
ClientDictionaries: map[string]string{},
|
||||
RequestProcessors: &[]*ReqProcessorJsnCfg{
|
||||
{},
|
||||
},
|
||||
}
|
||||
@@ -365,7 +381,9 @@ func TestRadiusAgentCloneSection(t *testing.T) {
|
||||
ClientDictionaries: map[string]string{
|
||||
"radius_dict1": "radius_val1",
|
||||
},
|
||||
SessionSConns: []string{"*birpc"},
|
||||
SessionSConns: []string{"*internal"},
|
||||
StatSConns: []string{"*internal"},
|
||||
ThresholdSConns: []string{"*internal"},
|
||||
RequestProcessors: []*RequestProcessor{
|
||||
{
|
||||
ID: "REQ_PROC1",
|
||||
@@ -385,7 +403,9 @@ func TestRadiusAgentCloneSection(t *testing.T) {
|
||||
ClientDictionaries: map[string]string{
|
||||
"radius_dict1": "radius_val1",
|
||||
},
|
||||
SessionSConns: []string{"*birpc"},
|
||||
SessionSConns: []string{"*internal"},
|
||||
StatSConns: []string{"*internal"},
|
||||
ThresholdSConns: []string{"*internal"},
|
||||
RequestProcessors: []*RequestProcessor{
|
||||
{
|
||||
ID: "REQ_PROC1",
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/cgrates/birpc/context"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
// RadiusAgentCfg the config section that describes the Radius Agent
|
||||
type RadiusAgentCfg struct {
|
||||
Enabled bool
|
||||
ListenNet string // udp or tcp
|
||||
ListenAuth string
|
||||
ListenAcct string
|
||||
ClientSecrets map[string]string
|
||||
ClientDictionaries map[string]string
|
||||
SessionSConns []string
|
||||
RequestProcessors []*RequestProcessor
|
||||
}
|
||||
|
||||
// loadRadiusAgentCfg loads the RadiusAgent section of the configuration
|
||||
func (ra *RadiusAgentCfg) Load(ctx *context.Context, jsnCfg ConfigDB, _ *CGRConfig) (err error) {
|
||||
jsnRACfg := new(RadiusAgentJsonCfg)
|
||||
if err = jsnCfg.GetSection(ctx, RadiusAgentJSON, jsnRACfg); err != nil {
|
||||
return
|
||||
}
|
||||
return ra.loadFromJSONCfg(jsnRACfg)
|
||||
}
|
||||
|
||||
func (ra *RadiusAgentCfg) loadFromJSONCfg(jsnCfg *RadiusAgentJsonCfg) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
ra.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.Listen_net != nil {
|
||||
ra.ListenNet = *jsnCfg.Listen_net
|
||||
}
|
||||
if jsnCfg.Listen_auth != nil {
|
||||
ra.ListenAuth = *jsnCfg.Listen_auth
|
||||
}
|
||||
if jsnCfg.Listen_acct != nil {
|
||||
ra.ListenAcct = *jsnCfg.Listen_acct
|
||||
}
|
||||
if jsnCfg.Client_secrets != nil {
|
||||
for k, v := range jsnCfg.Client_secrets {
|
||||
ra.ClientSecrets[k] = v
|
||||
}
|
||||
}
|
||||
if jsnCfg.Client_dictionaries != nil {
|
||||
for k, v := range jsnCfg.Client_dictionaries {
|
||||
ra.ClientDictionaries[k] = v
|
||||
}
|
||||
}
|
||||
if jsnCfg.Sessions_conns != nil {
|
||||
ra.SessionSConns = tagInternalConns(*jsnCfg.Sessions_conns, utils.MetaSessionS)
|
||||
}
|
||||
ra.RequestProcessors, err = appendRequestProcessors(ra.RequestProcessors, jsnCfg.Request_processors)
|
||||
return
|
||||
}
|
||||
|
||||
// AsMapInterface returns the config as a map[string]any
|
||||
func (ra RadiusAgentCfg) AsMapInterface() any {
|
||||
mp := map[string]any{
|
||||
utils.EnabledCfg: ra.Enabled,
|
||||
utils.ListenNetCfg: ra.ListenNet,
|
||||
utils.ListenAuthCfg: ra.ListenAuth,
|
||||
utils.ListenAcctCfg: ra.ListenAcct,
|
||||
}
|
||||
|
||||
requestProcessors := make([]map[string]any, len(ra.RequestProcessors))
|
||||
for i, item := range ra.RequestProcessors {
|
||||
requestProcessors[i] = item.AsMapInterface()
|
||||
}
|
||||
mp[utils.RequestProcessorsCfg] = requestProcessors
|
||||
|
||||
if ra.SessionSConns != nil {
|
||||
mp[utils.SessionSConnsCfg] = stripInternalConns(ra.SessionSConns)
|
||||
}
|
||||
clientSecrets := make(map[string]string)
|
||||
for k, v := range ra.ClientSecrets {
|
||||
clientSecrets[k] = v
|
||||
}
|
||||
mp[utils.ClientSecretsCfg] = clientSecrets
|
||||
clientDictionaries := make(map[string]string)
|
||||
for k, v := range ra.ClientDictionaries {
|
||||
clientDictionaries[k] = v
|
||||
}
|
||||
mp[utils.ClientDictionariesCfg] = clientDictionaries
|
||||
return mp
|
||||
}
|
||||
|
||||
func (RadiusAgentCfg) SName() string { return RadiusAgentJSON }
|
||||
func (ra RadiusAgentCfg) CloneSection() Section { return ra.Clone() }
|
||||
|
||||
// Clone returns a deep copy of RadiusAgentCfg
|
||||
func (ra RadiusAgentCfg) Clone() (cln *RadiusAgentCfg) {
|
||||
cln = &RadiusAgentCfg{
|
||||
Enabled: ra.Enabled,
|
||||
ListenNet: ra.ListenNet,
|
||||
ListenAuth: ra.ListenAuth,
|
||||
ListenAcct: ra.ListenAcct,
|
||||
ClientSecrets: make(map[string]string),
|
||||
ClientDictionaries: make(map[string]string),
|
||||
}
|
||||
if ra.SessionSConns != nil {
|
||||
cln.SessionSConns = slices.Clone(ra.SessionSConns)
|
||||
}
|
||||
for k, v := range ra.ClientSecrets {
|
||||
cln.ClientSecrets[k] = v
|
||||
}
|
||||
for k, v := range ra.ClientDictionaries {
|
||||
cln.ClientDictionaries[k] = v
|
||||
}
|
||||
if ra.RequestProcessors != nil {
|
||||
cln.RequestProcessors = make([]*RequestProcessor, len(ra.RequestProcessors))
|
||||
for i, req := range ra.RequestProcessors {
|
||||
cln.RequestProcessors[i] = req.Clone()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Radius Agent configuration section
|
||||
type RadiusAgentJsonCfg struct {
|
||||
Enabled *bool
|
||||
Listen_net *string
|
||||
Listen_auth *string
|
||||
Listen_acct *string
|
||||
Client_secrets map[string]string
|
||||
Client_dictionaries map[string]string
|
||||
Sessions_conns *[]string
|
||||
Request_processors *[]*ReqProcessorJsnCfg
|
||||
}
|
||||
|
||||
func diffRadiusAgentJsonCfg(d *RadiusAgentJsonCfg, v1, v2 *RadiusAgentCfg) *RadiusAgentJsonCfg {
|
||||
if d == nil {
|
||||
d = new(RadiusAgentJsonCfg)
|
||||
}
|
||||
if v1.Enabled != v2.Enabled {
|
||||
d.Enabled = utils.BoolPointer(v2.Enabled)
|
||||
}
|
||||
if v1.ListenNet != v2.ListenNet {
|
||||
d.Listen_net = utils.StringPointer(v2.ListenNet)
|
||||
}
|
||||
if v1.ListenAuth != v2.ListenAuth {
|
||||
d.Listen_auth = utils.StringPointer(v2.ListenAuth)
|
||||
}
|
||||
if v1.ListenAcct != v2.ListenAcct {
|
||||
d.Listen_acct = utils.StringPointer(v2.ListenAcct)
|
||||
}
|
||||
d.Client_secrets = diffMapString(d.Client_secrets, v1.ClientSecrets, v2.ClientSecrets)
|
||||
d.Client_dictionaries = diffMapString(d.Client_dictionaries, v1.ClientDictionaries, v2.ClientDictionaries)
|
||||
if !slices.Equal(v1.SessionSConns, v2.SessionSConns) {
|
||||
d.Sessions_conns = utils.SliceStringPointer(stripInternalConns(v2.SessionSConns))
|
||||
}
|
||||
d.Request_processors = diffReqProcessorsJsnCfg(d.Request_processors, v1.RequestProcessors, v2.RequestProcessors)
|
||||
return d
|
||||
}
|
||||
|
||||
func diffMapString(d, v1, v2 map[string]string) map[string]string {
|
||||
if d == nil {
|
||||
d = make(map[string]string)
|
||||
}
|
||||
for k, v := range v2 {
|
||||
if val, has := v1[k]; !has || val != v {
|
||||
d[k] = v
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func diffMapStringSlice(d, v1, v2 map[string][]string) map[string][]string {
|
||||
if d == nil {
|
||||
d = make(map[string][]string)
|
||||
}
|
||||
for k, v := range v2 {
|
||||
if val, has := v1[k]; !has || !slices.Equal(val, v) {
|
||||
d[k] = v
|
||||
}
|
||||
}
|
||||
return d
|
||||
}
|
||||
Reference in New Issue
Block a user