Make Action Profiles storable in MySQL and Postgres

This commit is contained in:
arberkatellari
2025-11-04 10:36:03 +02:00
committed by Dan Christian Bogos
parent 89653a9c80
commit d78f34bdc5
18 changed files with 346 additions and 53 deletions

View File

@@ -291,6 +291,120 @@ func (ap *ActionProfile) FieldAsInterface(fldPath []string) (_ any, err error) {
}
}
// AsMapStringInterface converts ActionProfile struct to map[string]any
func (ap *ActionProfile) AsMapStringInterface() map[string]any {
if ap == nil {
return nil
}
return map[string]any{
Tenant: ap.Tenant,
ID: ap.ID,
FilterIDs: ap.FilterIDs,
Weights: ap.Weights,
Blockers: ap.Blockers,
Schedule: ap.Schedule,
Targets: ap.Targets,
Actions: ap.Actions,
}
}
// MapStringInterfaceToActionProfile converts map[string]any to ActionProfile struct
func MapStringInterfaceToActionProfile(m map[string]any) (ap *ActionProfile, err error) {
ap = &ActionProfile{}
if v, ok := m[Tenant].(string); ok {
ap.Tenant = v
}
if v, ok := m[ID].(string); ok {
ap.ID = v
}
ap.FilterIDs = InterfaceToStringSlice(m[FilterIDs])
ap.Weights = InterfaceToDynamicWeights(m[Weights])
ap.Blockers = InterfaceToDynamicBlockers(m[Blockers])
if v, ok := m[Schedule].(string); ok {
ap.Schedule = v
}
ap.Targets = InterfaceToMapStringStringSet(m[Targets])
if ap.Actions, err = InterfaceToAPActions(m[Actions]); err != nil {
return nil, err
}
return ap, nil
}
// InterfaceToAPActions converts any to []*APAction
func InterfaceToAPActions(m any) ([]*APAction, error) {
v, ok := m.([]any)
if !ok {
return nil, nil
}
actions := make([]*APAction, 0, len(v))
for _, actionAny := range v {
if actionMap, ok := actionAny.(map[string]any); ok {
action, err := MapToAPAction(actionMap)
if err != nil {
return nil, err
}
actions = append(actions, action)
}
}
return actions, nil
}
// MapToAPAction converts map[string]any to APAction struct
func MapToAPAction(m map[string]any) (*APAction, error) {
action := &APAction{}
if v, ok := m[ID].(string); ok {
action.ID = v
}
action.FilterIDs = InterfaceToStringSlice(m[FilterIDs])
if v, ok := m[TTL].(string); ok {
if dur, err := time.ParseDuration(v); err != nil {
return nil, err
} else {
action.TTL = dur
}
} else if v, ok := m[TTL].(float64); ok { // for -1 cases
action.TTL = time.Duration(v)
}
if v, ok := m[Type].(string); ok {
action.Type = v
}
if v, ok := m[Opts].(map[string]any); ok {
action.Opts = v
}
action.Weights = InterfaceToDynamicWeights(m[Weights])
action.Blockers = InterfaceToDynamicBlockers(m[Blockers])
if v, ok := m[Diktats].([]any); ok {
action.Diktats = make([]*APDiktat, 0, len(v))
for _, diktatAny := range v {
if diktatMap, ok := diktatAny.(map[string]any); ok {
diktat, err := MapToAPDiktat(diktatMap)
if err != nil {
return nil, err
}
action.Diktats = append(action.Diktats, diktat)
}
}
}
return action, nil
}
// MapToAPDiktat converts map[string]any to APDiktat struct
func MapToAPDiktat(m map[string]any) (*APDiktat, error) {
diktat := &APDiktat{}
if v, ok := m[ID].(string); ok {
diktat.ID = v
}
diktat.FilterIDs = InterfaceToStringSlice(m[FilterIDs])
if v, ok := m[Opts].(map[string]any); ok {
diktat.Opts = v
}
diktat.Weights = InterfaceToDynamicWeights(m[Weights])
diktat.Blockers = InterfaceToDynamicBlockers(m[Blockers])
return diktat, nil
}
// APAction defines action related information used within an ActionProfile.
type APAction struct {
ID string // Action ID

View File

@@ -1897,27 +1897,28 @@ const (
// Table Name
const (
TBLTPResources = "tp_resources"
TBLTPStats = "tp_stats"
TBLTPRankings = "tp_rankings"
TBLTPTrends = "tp_trends"
TBLTPThresholds = "tp_thresholds"
TBLTPFilters = "tp_filters"
SessionCostsTBL = "session_costs"
CDRsTBL = "cdrs"
TBLTPRoutes = "tp_routes"
TBLTPAttributes = "tp_attributes"
TBLTPChargers = "tp_chargers"
TBLVersions = "versions"
TBLAccounts = "accounts"
TBLIPProfiles = "ip_profiles"
TBLIPAllocations = "ip_allocations"
OldSMCosts = "sm_costs"
TBLTPDispatchers = "tp_dispatcher_profiles"
TBLTPDispatcherHosts = "tp_dispatcher_hosts"
TBLTPRateProfiles = "tp_rate_profiles"
TBLTPActionProfiles = "tp_action_profiles"
TBLTPAccounts = "tp_accounts"
TBLTPResources = "tp_resources"
TBLTPStats = "tp_stats"
TBLTPRankings = "tp_rankings"
TBLTPTrends = "tp_trends"
TBLTPThresholds = "tp_thresholds"
TBLTPFilters = "tp_filters"
SessionCostsTBL = "session_costs"
CDRsTBL = "cdrs"
TBLTPRoutes = "tp_routes"
TBLTPAttributes = "tp_attributes"
TBLTPChargers = "tp_chargers"
TBLVersions = "versions"
TBLAccounts = "accounts"
TBLIPProfiles = "ip_profiles"
TBLIPAllocations = "ip_allocations"
TBLActionProfilesJSON = "action_profiles"
OldSMCosts = "sm_costs"
TBLTPDispatchers = "tp_dispatcher_profiles"
TBLTPDispatcherHosts = "tp_dispatcher_hosts"
TBLTPRateProfiles = "tp_rate_profiles"
TBLTPActionProfiles = "tp_action_profiles"
TBLTPAccounts = "tp_accounts"
)
// Cache Name

View File

@@ -658,7 +658,9 @@ func MapStringInterfaceToIPProfile(m map[string]any) (*IPProfile, error) {
ipp.FilterIDs = InterfaceToStringSlice(m[FilterIDs])
ipp.Weights = InterfaceToDynamicWeights(m[Weights])
if v, ok := m[TTL].(string); ok {
if dur, err := time.ParseDuration(v); err == nil {
if dur, err := time.ParseDuration(v); err != nil {
return nil, err
} else {
ipp.TTL = dur
}
} else if v, ok := m[TTL].(float64); ok { // for -1 cases
@@ -752,7 +754,7 @@ func IPAllocationsLockKey(tnt, id string) string {
return ConcatenatedKey(CacheIPAllocations, tnt, id)
}
// AsMapStringInterface converts IPProfile struct to map[string]any
// AsMapStringInterface converts IPAllocations struct to map[string]any
func (p *IPAllocations) AsMapStringInterface() map[string]any {
if p == nil {
return nil
@@ -766,7 +768,7 @@ func (p *IPAllocations) AsMapStringInterface() map[string]any {
}
// MapStringInterfaceToIPAllocations converts map[string]any to IPAllocations struct
func MapStringInterfaceToIPAllocations(m map[string]any) (*IPAllocations, error) {
func MapStringInterfaceToIPAllocations(m map[string]any) *IPAllocations {
ipa := &IPAllocations{}
if v, ok := m[Tenant].(string); ok {
@@ -777,7 +779,7 @@ func MapStringInterfaceToIPAllocations(m map[string]any) (*IPAllocations, error)
}
ipa.Allocations = InterfaceToAllocations(m[Allocations])
ipa.TTLIndex = InterfaceToStringSlice(m[TTLIndex])
return ipa, nil
return ipa
}
// InterfaceToAllocations converts any to map[string]*PoolAllocation

View File

@@ -161,3 +161,22 @@ func (s StringSet) FieldAsString(fldPath []string) (_ string, err error) {
}
return "{}", nil // noting in it as is a empty structure
}
// InterfaceToMapStringStringSet converts map[string]any to map[string]StringSet
func InterfaceToMapStringStringSet(m any) map[string]StringSet {
v, ok := m.(map[string]any)
if !ok {
return nil
}
targets := make(map[string]StringSet)
for key, val := range v {
if valMap, ok := val.(map[string]any); ok {
stringSet := make(StringSet)
for k := range valMap {
stringSet[k] = struct{}{}
}
targets[key] = stringSet
}
}
return targets
}