Revert "chore: simplify config serialisation"
This reverts commit 14fdabbcb6.
This commit is contained in:
parent
14fdabbcb6
commit
04223e501d
6 changed files with 116 additions and 19 deletions
|
|
@ -54,7 +54,7 @@ func runConfig(cmd *cobra.Command, args []string) {
|
|||
}
|
||||
|
||||
for _, c := range configurable {
|
||||
fmt.Println(config.NameForID(c.ID), "type:"+c.Type, redactMap(c.Data))
|
||||
fmt.Println(config.NameForID(c.ID), "type:"+c.Type, redactJson(c.Value))
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func runConfigDelete(cmd *cobra.Command, args []string) {
|
|||
log.FATAL.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(config.NameForID(c.ID), "type:"+c.Type, c.Data)
|
||||
fmt.Println(config.NameForID(c.ID), "type:"+c.Type, c.Value)
|
||||
|
||||
switch c.Class {
|
||||
case templates.Charger:
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ func runDevice(cmd *cobra.Command, args []string) {
|
|||
|
||||
for _, d := range devs {
|
||||
fmt.Printf("%d. %s\n", d.ID, d.Type)
|
||||
fmt.Println(d.Data)
|
||||
fmt.Println(d.Value)
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net"
|
||||
"os"
|
||||
"regexp"
|
||||
|
|
@ -64,15 +64,20 @@ func redact(src string) string {
|
|||
ReplaceAllString(src, "$1: *****")
|
||||
}
|
||||
|
||||
func redactMap(src map[string]any) map[string]any {
|
||||
res := maps.Clone(src)
|
||||
for k := range res {
|
||||
func redactJson(src string) string {
|
||||
var j map[string]any
|
||||
if err := json.Unmarshal([]byte(src), &j); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for k := range j {
|
||||
if slices.Contains(redactSecrets, k) {
|
||||
res[k] = "*****"
|
||||
j[k] = "*****"
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
res, _ := json.Marshal(j)
|
||||
return string(res)
|
||||
}
|
||||
|
||||
// fatal logs a fatal error and runs shutdown functions before terminating
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"maps"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ type Config struct {
|
|||
ID int `gorm:"primarykey"`
|
||||
Class templates.Class
|
||||
Type string
|
||||
Data map[string]any `gorm:"value,type:string,serializer:json"`
|
||||
Value string
|
||||
}
|
||||
|
||||
// TODO remove- migration only
|
||||
|
|
@ -30,7 +30,7 @@ func (d *Config) Named() Named {
|
|||
res := Named{
|
||||
Name: NameForID(d.ID),
|
||||
Type: d.Type,
|
||||
Other: maps.Clone(d.Data),
|
||||
Other: d.detailsAsMap(),
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
@ -39,11 +39,26 @@ func (d *Config) Named() Named {
|
|||
func (d *Config) Typed() Typed {
|
||||
res := Typed{
|
||||
Type: d.Type,
|
||||
Other: maps.Clone(d.Data),
|
||||
Other: d.detailsAsMap(),
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// detailsAsMap converts device details to map
|
||||
func (d *Config) detailsAsMap() map[string]any {
|
||||
res := make(map[string]any)
|
||||
if err := json.Unmarshal([]byte(d.Value), &res); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// detailsFromMap converts map to device details
|
||||
func detailsFromMap(config map[string]any) (string, error) {
|
||||
b, err := json.Marshal(config)
|
||||
return string(b), err
|
||||
}
|
||||
|
||||
// Update updates a config's details to the database
|
||||
func (d *Config) Update(conf map[string]any) error {
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
|
|
@ -52,7 +67,11 @@ func (d *Config) Update(conf map[string]any) error {
|
|||
return err
|
||||
}
|
||||
|
||||
d.Data = conf
|
||||
val, err := detailsFromMap(conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Value = val
|
||||
|
||||
return tx.Save(&d).Error
|
||||
})
|
||||
|
|
@ -66,10 +85,17 @@ func (d *Config) PartialUpdate(conf map[string]any) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := mergo.Merge(&config.Data, conf, mergo.WithOverride); err != nil {
|
||||
actual := d.detailsAsMap()
|
||||
if err := mergo.Merge(&actual, conf, mergo.WithOverride); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
val, err := detailsFromMap(actual)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.Value = val
|
||||
|
||||
return tx.Save(&d).Error
|
||||
})
|
||||
}
|
||||
|
|
@ -84,7 +110,66 @@ var db *gorm.DB
|
|||
func Init(instance *gorm.DB) error {
|
||||
db = instance
|
||||
m := db.Migrator()
|
||||
return m.AutoMigrate(new(Config))
|
||||
|
||||
for old, new := range map[string]string{
|
||||
"devices": "configs",
|
||||
"device_details": "config_details",
|
||||
} {
|
||||
if m.HasTable(old) {
|
||||
if err := m.RenameTable(old, new); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := m.AutoMigrate(new(Config))
|
||||
|
||||
if err == nil && m.HasTable("config_details") {
|
||||
err = m.AutoMigrate(new(ConfigDetails))
|
||||
|
||||
if err == nil && m.HasConstraint(new(ConfigDetails), "fk_devices_details") {
|
||||
err = m.DropConstraint(new(ConfigDetails), "fk_devices_details")
|
||||
}
|
||||
if err == nil && m.HasColumn(new(ConfigDetails), "device_id") {
|
||||
err = m.DropColumn(new(ConfigDetails), "device_id")
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && m.HasTable("config_details") {
|
||||
var devices []Config
|
||||
if err := db.Where(&Config{}).Find(&devices).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// migrate ConfigDetails into Config.Value
|
||||
for _, dev := range devices {
|
||||
var details []ConfigDetails
|
||||
if err := db.Where(&ConfigDetails{ConfigID: dev.ID}).Find(&details).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res := make(map[string]any)
|
||||
for _, detail := range details {
|
||||
res[detail.Key] = detail.Value
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
val, err := detailsFromMap(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dev.Value = val
|
||||
|
||||
if err := db.Save(&dev).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = m.DropTable("config_details")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// NameForID returns a unique config name for the given id
|
||||
|
|
@ -105,7 +190,7 @@ func ConfigurationsByClass(class templates.Class) ([]Config, error) {
|
|||
// remove devices without details
|
||||
res := make([]Config, 0, len(devices))
|
||||
for _, dev := range devices {
|
||||
if len(dev.Data) > 0 {
|
||||
if len(dev.Value) > 0 {
|
||||
res = append(res, dev)
|
||||
}
|
||||
}
|
||||
|
|
@ -122,13 +207,18 @@ func ConfigByID(id int) (Config, error) {
|
|||
|
||||
// AddConfig adds a new config to the database
|
||||
func AddConfig(class templates.Class, typ string, conf map[string]any) (Config, error) {
|
||||
val, err := detailsFromMap(conf)
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
|
||||
config := Config{
|
||||
Class: class,
|
||||
Type: typ,
|
||||
Data: conf,
|
||||
Value: val,
|
||||
}
|
||||
|
||||
err := db.Create(&config).Error
|
||||
err = db.Create(&config).Error
|
||||
|
||||
return config, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ type Device[T any] interface {
|
|||
type ConfigurableDevice[T any] interface {
|
||||
Device[T]
|
||||
ID() int
|
||||
// Assign(T)
|
||||
// Update1(map[string]any) error
|
||||
Update(map[string]any, T) error
|
||||
PartialUpdate(map[string]any, T) error
|
||||
Delete() error
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue