fix: align admin behavior and Kratos integrations
This commit is contained in:
@@ -53,14 +53,22 @@ func setYAMLMapping(node *yaml.Node, key string, value any) error {
|
||||
}
|
||||
|
||||
func (d *Data) persistConfig() error {
|
||||
return d.persistConfigValues(d.config, d.admin)
|
||||
dataConfig, adminConfig := d.runtime.Values()
|
||||
return d.persistConfigValues(dataConfig, adminConfig)
|
||||
}
|
||||
|
||||
func (d *Data) persistConfigValues(dataConfig *conf.Data, adminConfig *conf.AdminBackend) error {
|
||||
if d.admin == nil || d.admin.ConfigPath == "" {
|
||||
d.configMu.Lock()
|
||||
defer d.configMu.Unlock()
|
||||
return d.persistConfigValuesLocked(dataConfig, adminConfig)
|
||||
}
|
||||
|
||||
func (d *Data) persistConfigValuesLocked(dataConfig *conf.Data, adminConfig *conf.AdminBackend) error {
|
||||
if adminConfig == nil || adminConfig.ConfigPath == "" {
|
||||
return nil
|
||||
}
|
||||
raw, err := os.ReadFile(d.admin.ConfigPath)
|
||||
configPath := adminConfig.ConfigPath
|
||||
raw, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -86,10 +94,10 @@ func (d *Data) persistConfigValues(dataConfig *conf.Data, adminConfig *conf.Admi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.MkdirAll(filepath.Dir(d.admin.ConfigPath), 0o755); err != nil {
|
||||
if err = os.MkdirAll(filepath.Dir(configPath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
temporary, err := os.CreateTemp(filepath.Dir(d.admin.ConfigPath), ".kra-config-*.yaml")
|
||||
temporary, err := os.CreateTemp(filepath.Dir(configPath), ".kra-config-*.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -106,33 +114,24 @@ func (d *Data) persistConfigValues(dataConfig *conf.Data, adminConfig *conf.Admi
|
||||
if err = temporary.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tempName, d.admin.ConfigPath)
|
||||
return os.Rename(tempName, configPath)
|
||||
}
|
||||
|
||||
func (d *Data) reloadConfig(ctx context.Context) error {
|
||||
if d.admin == nil || d.admin.ConfigPath == "" {
|
||||
d.configMu.Lock()
|
||||
defer d.configMu.Unlock()
|
||||
configPath := d.runtime.ConfigPath()
|
||||
if configPath == "" {
|
||||
return fmt.Errorf("configuration path is not set")
|
||||
}
|
||||
raw, err := os.ReadFile(d.admin.ConfigPath)
|
||||
next, err := readBootstrap(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var plain map[string]any
|
||||
if err = yaml.Unmarshal(raw, &plain); err != nil {
|
||||
return err
|
||||
}
|
||||
encoded, err := json.Marshal(plain)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var next conf.Bootstrap
|
||||
if err = (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(encoded, &next); err != nil {
|
||||
return err
|
||||
}
|
||||
if next.Data == nil || next.Data.Database == nil || next.Admin == nil {
|
||||
return fmt.Errorf("data.database and admin configuration are required")
|
||||
}
|
||||
next.Admin.ConfigPath = d.admin.ConfigPath
|
||||
next.Admin.ConfigPath = configPath
|
||||
candidateDB, err := openDatabase(next.Data.Database, false, "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("reload database: %w", err)
|
||||
@@ -150,35 +149,49 @@ func (d *Data) reloadConfig(ctx context.Context) error {
|
||||
} else if err = sqlDB.PingContext(ctx); err != nil {
|
||||
return fmt.Errorf("reload database: %w", err)
|
||||
}
|
||||
if err = migrateAll(candidateDB.WithContext(ctx)); err != nil {
|
||||
return fmt.Errorf("reload database migrations: %w", err)
|
||||
if next.Admin.System == nil || !next.Admin.System.DisableAutoMigrate {
|
||||
if err = migrateAll(candidateDB.WithContext(ctx)); err != nil {
|
||||
return fmt.Errorf("reload database migrations: %w", err)
|
||||
}
|
||||
}
|
||||
candidateStorage, err := buildFileStorage(next.Admin)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reload storage: %w", err)
|
||||
}
|
||||
candidateRedis := openRedis(next.Data.Redis)
|
||||
useRedis := next.Admin.System != nil && next.Admin.System.UseRedis
|
||||
candidateRedis := openRedis(next.Data.Redis, useRedis)
|
||||
candidateDBList, err := openDatabaseList(next.Data.DatabaseList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.mu.Lock()
|
||||
oldDB, oldRedis := d.gormDB, d.redis
|
||||
d.gormDB, d.redis = candidateDB, candidateRedis
|
||||
proto.Reset(d.config)
|
||||
proto.Merge(d.config, next.Data)
|
||||
proto.Reset(d.admin)
|
||||
proto.Merge(d.admin, next.Admin)
|
||||
d.database = d.config.Database
|
||||
d.mu.Unlock()
|
||||
d.gormDB.replace(candidateDB)
|
||||
d.replaceDatabaseList(candidateDBList)
|
||||
d.redis.replace(candidateRedis)
|
||||
d.runtime.Replace(next.Data, next.Admin)
|
||||
if d.storage != nil {
|
||||
d.storage.replace(candidateStorage)
|
||||
}
|
||||
closeCandidate = false
|
||||
if oldDB != nil {
|
||||
if sqlDB, closeErr := oldDB.DB(); closeErr == nil {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}
|
||||
if oldRedis != nil {
|
||||
_ = oldRedis.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readBootstrap(configPath string) (*conf.Bootstrap, error) {
|
||||
raw, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var plain map[string]any
|
||||
if err = yaml.Unmarshal(raw, &plain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encoded, err := json.Marshal(plain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var next conf.Bootstrap
|
||||
if err = (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(encoded, &next); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &next, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user