/* 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 Affero 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see */ package config import ( "os" "path" "path/filepath" "time" "github.com/cgrates/cgrates/utils" ) // NewDfltLoaderSCfg returns the first cached default value for a LoaderSCfg connection func NewDfltLoaderSCfg() *LoaderSCfg { if dfltLoaderConfig == nil { return new(LoaderSCfg) } dfltVal := *dfltLoaderConfig return &dfltVal } // LoaderSCfgs to export some methods for LoaderS profiles type LoaderSCfgs []*LoaderSCfg // AsMapInterface returns the config as a map[string]any func (ldrs LoaderSCfgs) AsMapInterface(separator string) (loaderCfg []map[string]any) { loaderCfg = make([]map[string]any, len(ldrs)) for i, item := range ldrs { loaderCfg[i] = item.AsMapInterface(separator) } return } // Enabled returns true if Loader Service is enabled func (ldrs LoaderSCfgs) Enabled() bool { for _, ldr := range ldrs { if ldr.Enabled { return true } } return false } // Clone itself into a new LoaderSCfgs func (ldrs LoaderSCfgs) Clone() (cln LoaderSCfgs) { cln = make(LoaderSCfgs, len(ldrs)) for i, ldr := range ldrs { cln[i] = ldr.Clone() } return } // LoaderSCfg the config for a loader type LoaderSCfg struct { ID string Enabled bool Tenant string DryRun bool RunDelay time.Duration LockFilePath string CacheSConns []string FieldSeparator string TpInDir string TpOutDir string Data []*LoaderDataType } // LoaderDataType the template for profile loading type LoaderDataType struct { Type string Filename string Flags utils.FlagsWithParams Fields []*FCTemplate } func (lData *LoaderDataType) loadFromJSONCfg(jsnCfg *LoaderJsonDataType, msgTemplates map[string][]*FCTemplate, separator string) (err error) { if jsnCfg == nil { return nil } if jsnCfg.Type != nil { lData.Type = *jsnCfg.Type } if jsnCfg.File_name != nil { lData.Filename = *jsnCfg.File_name } if jsnCfg.Flags != nil { lData.Flags = utils.FlagsWithParamsFromSlice(*jsnCfg.Flags) } if jsnCfg.Fields != nil { if lData.Fields, err = FCTemplatesFromFCTemplatesJSONCfg(*jsnCfg.Fields, separator); err != nil { return } if tpls, err := InflateTemplates(lData.Fields, msgTemplates); err != nil { return err } else if tpls != nil { lData.Fields = tpls } } return nil } func (l *LoaderSCfg) loadFromJSONCfg(jsnCfg *LoaderJsonCfg, msgTemplates map[string][]*FCTemplate, separator string) (err error) { if jsnCfg == nil { return nil } if jsnCfg.ID != nil { l.ID = *jsnCfg.ID } if jsnCfg.Enabled != nil { l.Enabled = *jsnCfg.Enabled } if jsnCfg.Tenant != nil { l.Tenant = *jsnCfg.Tenant } if jsnCfg.Dry_run != nil { l.DryRun = *jsnCfg.Dry_run } if jsnCfg.Run_delay != nil { if l.RunDelay, err = utils.ParseDurationWithNanosecs(*jsnCfg.Run_delay); err != nil { return } } if jsnCfg.Caches_conns != nil { l.CacheSConns = make([]string, len(*jsnCfg.Caches_conns)) for idx, connID := range *jsnCfg.Caches_conns { // if we have the connection internal we change the name so we can have internal rpc for each subsystem if connID == utils.MetaInternal { l.CacheSConns[idx] = utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches) } else { l.CacheSConns[idx] = connID } } } if jsnCfg.Field_separator != nil { l.FieldSeparator = *jsnCfg.Field_separator } if jsnCfg.Tp_in_dir != nil { l.TpInDir = *jsnCfg.Tp_in_dir } if jsnCfg.Tp_out_dir != nil { l.TpOutDir = *jsnCfg.Tp_out_dir } if jsnCfg.Lockfile_path != nil { l.LockFilePath = *jsnCfg.Lockfile_path } if jsnCfg.Data != nil { data := make([]*LoaderDataType, len(*jsnCfg.Data)) for idx, jsnLoCfg := range *jsnCfg.Data { data[idx] = new(LoaderDataType) if err := data[idx].loadFromJSONCfg(jsnLoCfg, msgTemplates, separator); err != nil { return err } } l.Data = data } return nil } func (l LoaderSCfg) GetLockFilePath() (pathL string) { pathL = l.LockFilePath if !filepath.IsAbs(pathL) { pathL = path.Join(l.TpInDir, pathL) } if file, err := os.Stat(pathL); err == nil && file.IsDir() { pathL = path.Join(pathL, l.ID+".lck") } return } // Clone itself into a new LoaderDataType func (lData LoaderDataType) Clone() (cln *LoaderDataType) { cln = &LoaderDataType{ Type: lData.Type, Filename: lData.Filename, Flags: lData.Flags.Clone(), Fields: make([]*FCTemplate, len(lData.Fields)), } for idx, val := range lData.Fields { cln.Fields[idx] = val.Clone() } return } // Clone itself into a new LoadersConfig func (l LoaderSCfg) Clone() (cln *LoaderSCfg) { cln = &LoaderSCfg{ ID: l.ID, Enabled: l.Enabled, Tenant: l.Tenant, DryRun: l.DryRun, RunDelay: l.RunDelay, LockFilePath: l.LockFilePath, CacheSConns: make([]string, len(l.CacheSConns)), FieldSeparator: l.FieldSeparator, TpInDir: l.TpInDir, TpOutDir: l.TpOutDir, Data: make([]*LoaderDataType, len(l.Data)), } copy(cln.CacheSConns, l.CacheSConns) for idx, fld := range l.Data { cln.Data[idx] = fld.Clone() } return } // AsMapInterface returns the config as a map[string]any func (lData *LoaderDataType) AsMapInterface(separator string) (initialMP map[string]any) { initialMP = map[string]any{ utils.TypeCf: lData.Type, utils.FilenameCfg: lData.Filename, utils.FlagsCfg: lData.Flags.SliceFlags(), } fields := make([]map[string]any, len(lData.Fields)) for i, item := range lData.Fields { fields[i] = item.AsMapInterface(separator) } initialMP[utils.FieldsCfg] = fields return } // AsMapInterface returns the config as a map[string]any func (l *LoaderSCfg) AsMapInterface(separator string) (initialMP map[string]any) { initialMP = map[string]any{ utils.IDCfg: l.ID, utils.TenantCfg: l.Tenant, utils.EnabledCfg: l.Enabled, utils.DryRunCfg: l.DryRun, utils.LockFilePathCfg: l.LockFilePath, utils.FieldSepCfg: l.FieldSeparator, utils.TpInDirCfg: l.TpInDir, utils.TpOutDirCfg: l.TpOutDir, utils.RunDelayCfg: "0", } if l.Data != nil { data := make([]map[string]any, len(l.Data)) for i, item := range l.Data { data[i] = item.AsMapInterface(separator) } initialMP[utils.DataCfg] = data } if l.RunDelay != 0 { initialMP[utils.RunDelayCfg] = l.RunDelay.String() } if l.CacheSConns != nil { cacheSConns := make([]string, len(l.CacheSConns)) for i, item := range l.CacheSConns { cacheSConns[i] = item if item == utils.ConcatenatedKey(utils.MetaInternal, utils.MetaCaches) { cacheSConns[i] = utils.MetaInternal } } initialMP[utils.CachesConnsCfg] = cacheSConns } return }