olivetin/service/internal/entities/storage.go

136 lines
2.8 KiB
Go

package entities
/**
* The ephemeralvariablemap is used "only" for variable substitution in config
* titles, shell arguments, etc, in the foorm of {{ key }}, like Jinja2.
*
* OliveTin itself really only ever "writes" to this map, mostly by loading
* EntityFiles, and the only form of "reading" is for the variable substitution
* in configs.
*/
import (
"strings"
"sync"
"github.com/OliveTin/OliveTin/internal/installationinfo"
)
type entityInstancesByKey map[string]*Entity
type entitiesByClass map[string]entityInstancesByKey
type variableBase struct {
OliveTin installationInfo
Entities entitiesByClass
CurrentEntity interface{}
Arguments map[string]string
}
type installationInfo struct {
Build *installationinfo.BuildInfo
Runtime *installationinfo.RuntimeInfo
}
var (
contents *variableBase
rwmutex = sync.RWMutex{}
)
func init() {
rwmutex.Lock()
contents = &variableBase{
OliveTin: installationInfo{
Build: installationinfo.Build,
Runtime: installationinfo.Runtime,
},
Entities: make(entitiesByClass, 0),
}
rwmutex.Unlock()
}
func GetAll() *variableBase {
rwmutex.RLock()
defer rwmutex.RUnlock()
return contents
}
func GetEntities() entitiesByClass {
rwmutex.RLock()
copiedEntities := make(entitiesByClass, len(contents.Entities))
for entityName, entityInstances := range contents.Entities {
copiedInstances := make(entityInstancesByKey, len(entityInstances))
for key, entity := range entityInstances {
copiedInstances[key] = entity
}
copiedEntities[entityName] = copiedInstances
}
rwmutex.RUnlock()
return copiedEntities
}
func GetEntityInstances(entityName string) entityInstancesByKey {
rwmutex.RLock()
defer rwmutex.RUnlock()
if entities, ok := contents.Entities[entityName]; ok {
copiedInstances := make(entityInstancesByKey, len(entities))
for key, entity := range entities {
copiedInstances[key] = entity
}
return copiedInstances
}
return make(entityInstancesByKey, 0)
}
func AddEntity(entityName string, entityKey string, data any) {
rwmutex.Lock()
if _, ok := contents.Entities[entityName]; !ok {
contents.Entities[entityName] = make(entityInstancesByKey, 0)
}
contents.Entities[entityName][entityKey] = &Entity{
Data: data,
UniqueKey: entityKey,
Title: findEntityTitle(data),
}
rwmutex.Unlock()
}
//gocyclo:ignore
func findEntityTitle(data any) string {
if mapData, ok := data.(map[string]any); ok {
keys := make(map[string]string)
for k := range mapData {
lookupKey := strings.ToLower(k)
keys[lookupKey] = k
}
for _, key := range []string{"title", "name", "id", "hostname", "host", "label"} {
if lookupKey, exists := keys[strings.ToLower(key)]; exists {
if value, ok := mapData[lookupKey]; ok {
if valueStr, ok := value.(string); ok {
return valueStr
}
}
}
}
}
return "Untitled Entity"
}