mirror of
https://github.com/safing/portbase
synced 2025-04-16 23:49:09 +00:00
Improve config import and export utils
This commit is contained in:
parent
01b03aa936
commit
4451b6985c
7 changed files with 109 additions and 45 deletions
|
@ -482,7 +482,6 @@ func (e *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Check for handler error.
|
||||
if err != nil {
|
||||
// if statusProvider, ok := err.(HTTPStatusProvider); ok {
|
||||
var statusProvider HTTPStatusProvider
|
||||
if errors.As(err, &statusProvider) {
|
||||
http.Error(w, err.Error(), statusProvider.HTTPStatus())
|
||||
|
|
|
@ -14,7 +14,7 @@ func parseAndReplaceConfig(jsonData string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
validationErrors := replaceConfig(m)
|
||||
validationErrors, _ := ReplaceConfig(m)
|
||||
if len(validationErrors) > 0 {
|
||||
return fmt.Errorf("%d errors, first: %w", len(validationErrors), validationErrors[0])
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func parseAndReplaceDefaultConfig(jsonData string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
validationErrors := replaceDefaultConfig(m)
|
||||
validationErrors, _ := ReplaceDefaultConfig(m)
|
||||
if len(validationErrors) > 0 {
|
||||
return fmt.Errorf("%d errors, first: %w", len(validationErrors), validationErrors[0])
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ func start() error {
|
|||
|
||||
err = loadConfig(false)
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
return err
|
||||
return fmt.Errorf("failed to load config file: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -325,6 +325,29 @@ func (option *Option) IsSetByUser() bool {
|
|||
return option.activeValue != nil
|
||||
}
|
||||
|
||||
// UserValue returns the value set by the user or nil if the value has not
|
||||
// been changed from the default.
|
||||
func (option *Option) UserValue() any {
|
||||
option.Lock()
|
||||
defer option.Unlock()
|
||||
|
||||
if option.activeValue == nil {
|
||||
return nil
|
||||
}
|
||||
return option.activeValue.getData(option)
|
||||
}
|
||||
|
||||
// ValidateValue checks if the given value is valid for the option.
|
||||
func (option *Option) ValidateValue(value any) error {
|
||||
option.Lock()
|
||||
defer option.Unlock()
|
||||
|
||||
if _, err := validateValue(option, value); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Export expors an option to a Record.
|
||||
func (option *Option) Export() (record.Record, error) {
|
||||
option.Lock()
|
||||
|
|
|
@ -45,7 +45,7 @@ func loadConfig(requireValidConfig bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
validationErrors := replaceConfig(newValues)
|
||||
validationErrors, _ := ReplaceConfig(newValues)
|
||||
if requireValidConfig && len(validationErrors) > 0 {
|
||||
return fmt.Errorf("encountered %d validation errors during config loading", len(validationErrors))
|
||||
}
|
||||
|
|
120
config/set.go
120
config/set.go
|
@ -37,70 +37,112 @@ func signalChanges() {
|
|||
module.TriggerEvent(ChangeEvent, nil)
|
||||
}
|
||||
|
||||
// replaceConfig sets the (prioritized) user defined config.
|
||||
func replaceConfig(newValues map[string]interface{}) []*ValidationError {
|
||||
var validationErrors []*ValidationError
|
||||
|
||||
// ValidateConfig validates the given configuration and returns all validation
|
||||
// errors as well as whether the given configuration contains unknown keys.
|
||||
func ValidateConfig(newValues map[string]interface{}) (validationErrors []*ValidationError, requiresRestart bool, containsUnknown bool) {
|
||||
// RLock the options because we are not adding or removing
|
||||
// options from the registration but rather only update the
|
||||
// options value which is guarded by the option's lock itself
|
||||
// options from the registration but rather only checking the
|
||||
// options value which is guarded by the option's lock itself.
|
||||
optionsLock.RLock()
|
||||
defer optionsLock.RUnlock()
|
||||
|
||||
var checked int
|
||||
for key, option := range options {
|
||||
newValue, ok := newValues[key]
|
||||
|
||||
option.Lock()
|
||||
option.activeValue = nil
|
||||
|
||||
if ok {
|
||||
valueCache, err := validateValue(option, newValue)
|
||||
if err == nil {
|
||||
option.activeValue = valueCache
|
||||
} else {
|
||||
validationErrors = append(validationErrors, err)
|
||||
}
|
||||
}
|
||||
checked++
|
||||
|
||||
handleOptionUpdate(option, true)
|
||||
option.Unlock()
|
||||
func() {
|
||||
option.Lock()
|
||||
defer option.Unlock()
|
||||
|
||||
_, err := validateValue(option, newValue)
|
||||
if err != nil {
|
||||
validationErrors = append(validationErrors, err)
|
||||
}
|
||||
|
||||
if option.RequiresRestart {
|
||||
requiresRestart = true
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
signalChanges()
|
||||
|
||||
return validationErrors
|
||||
return validationErrors, requiresRestart, checked < len(newValues)
|
||||
}
|
||||
|
||||
// replaceDefaultConfig sets the (fallback) default config.
|
||||
func replaceDefaultConfig(newValues map[string]interface{}) []*ValidationError {
|
||||
var validationErrors []*ValidationError
|
||||
|
||||
// ReplaceConfig sets the (prioritized) user defined config.
|
||||
func ReplaceConfig(newValues map[string]interface{}) (validationErrors []*ValidationError, requiresRestart bool) {
|
||||
// RLock the options because we are not adding or removing
|
||||
// options from the registration but rather only update the
|
||||
// options value which is guarded by the option's lock itself
|
||||
// options value which is guarded by the option's lock itself.
|
||||
optionsLock.RLock()
|
||||
defer optionsLock.RUnlock()
|
||||
|
||||
for key, option := range options {
|
||||
newValue, ok := newValues[key]
|
||||
|
||||
option.Lock()
|
||||
option.activeDefaultValue = nil
|
||||
if ok {
|
||||
valueCache, err := validateValue(option, newValue)
|
||||
if err == nil {
|
||||
option.activeDefaultValue = valueCache
|
||||
} else {
|
||||
validationErrors = append(validationErrors, err)
|
||||
func() {
|
||||
option.Lock()
|
||||
defer option.Unlock()
|
||||
|
||||
option.activeValue = nil
|
||||
if ok {
|
||||
valueCache, err := validateValue(option, newValue)
|
||||
if err == nil {
|
||||
option.activeValue = valueCache
|
||||
} else {
|
||||
validationErrors = append(validationErrors, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
handleOptionUpdate(option, true)
|
||||
option.Unlock()
|
||||
handleOptionUpdate(option, true)
|
||||
|
||||
if option.RequiresRestart {
|
||||
requiresRestart = true
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
signalChanges()
|
||||
|
||||
return validationErrors
|
||||
return validationErrors, requiresRestart
|
||||
}
|
||||
|
||||
// ReplaceDefaultConfig sets the (fallback) default config.
|
||||
func ReplaceDefaultConfig(newValues map[string]interface{}) (validationErrors []*ValidationError, requiresRestart bool) {
|
||||
// RLock the options because we are not adding or removing
|
||||
// options from the registration but rather only update the
|
||||
// options value which is guarded by the option's lock itself.
|
||||
optionsLock.RLock()
|
||||
defer optionsLock.RUnlock()
|
||||
|
||||
for key, option := range options {
|
||||
newValue, ok := newValues[key]
|
||||
|
||||
func() {
|
||||
option.Lock()
|
||||
defer option.Unlock()
|
||||
|
||||
option.activeDefaultValue = nil
|
||||
if ok {
|
||||
valueCache, err := validateValue(option, newValue)
|
||||
if err == nil {
|
||||
option.activeDefaultValue = valueCache
|
||||
} else {
|
||||
validationErrors = append(validationErrors, err)
|
||||
}
|
||||
}
|
||||
handleOptionUpdate(option, true)
|
||||
|
||||
if option.RequiresRestart {
|
||||
requiresRestart = true
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
signalChanges()
|
||||
|
||||
return validationErrors, requiresRestart
|
||||
}
|
||||
|
||||
// SetConfigOption sets a single value in the (prioritized) user defined config.
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestLayersGetters(t *testing.T) { //nolint:paralleltest
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
validationErrors := replaceConfig(mapData)
|
||||
validationErrors, _ := ReplaceConfig(mapData)
|
||||
if len(validationErrors) > 0 {
|
||||
t.Fatalf("%d errors, first: %s", len(validationErrors), validationErrors[0].Error())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue