mirror of https://github.com/grafana/grafana
Settings: Encapsulate settings within an extensible provider (#32219)
* Encapsulate settings with a provider with support for runtime reloads * SettingsProvider: reload is controlled by the services * naive impl of reload handlers for settings * working naive detection on new changes * Trigger settings reload from API endpoint * validation step added * validation of settings * Fix linting errors * Replace DB_Varchar by DB_NVarchar * Reduce settings columns (section, key) lenghts * wip db update logic * Db Settings: separate updates and removals * Fix: removes incorrectly added code * Minor code improvements * Runtime settings: moved oss -> ee * Remove no longer used setting.Cfg SAML-related fields * Rename file setting/settings.go => setting/provider.go * Apply suggestions from code review Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com> * Minor code improvements on OSS settings provider * Fix some login API tests * Correct some GoDoc comments * Apply suggestions from code review Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com> Co-authored-by: Leonard Gram <leo@xlson.com> Co-authored-by: Agnès Toulet <35176601+AgnesToulet@users.noreply.github.com>pull/33432/head^2
parent
df4181c43a
commit
c41b08bd59
@ -0,0 +1,141 @@ |
||||
package setting |
||||
|
||||
import ( |
||||
"errors" |
||||
"strings" |
||||
"time" |
||||
|
||||
"gopkg.in/ini.v1" |
||||
) |
||||
|
||||
var ( |
||||
ErrOperationNotPermitted = errors.New("operation not permitted") |
||||
) |
||||
|
||||
type ValidationError struct { |
||||
Errors []error |
||||
} |
||||
|
||||
func (v ValidationError) Error() string { |
||||
builder := strings.Builder{} |
||||
|
||||
for i, e := range v.Errors { |
||||
builder.WriteString(e.Error()) |
||||
if i != len(v.Errors)-1 { |
||||
builder.WriteString(", ") |
||||
} |
||||
} |
||||
|
||||
return builder.String() |
||||
} |
||||
|
||||
// Provider is a settings provider abstraction
|
||||
// with thread-safety and runtime updates.
|
||||
type Provider interface { |
||||
// Update
|
||||
Update(updates SettingsBag, removals SettingsRemovals) error |
||||
// KeyValue returns a key-value abstraction
|
||||
// for the given pair of section and key.
|
||||
KeyValue(section, key string) KeyValue |
||||
// Section returns a settings section
|
||||
// abstraction for the given section name.
|
||||
Section(section string) Section |
||||
// RegisterReloadHandler registers a handler for validation and reload
|
||||
// of configuration updates tied to a specific section
|
||||
RegisterReloadHandler(section string, handler ReloadHandler) |
||||
} |
||||
|
||||
// Section is a settings section copy
|
||||
// with all of its pairs of keys-values.
|
||||
type Section interface { |
||||
// KeyValue returns a key-value
|
||||
// abstraction for the given key.
|
||||
KeyValue(key string) KeyValue |
||||
} |
||||
|
||||
// KeyValue represents a settings key-value
|
||||
// for a given pair of section and key.
|
||||
type KeyValue interface { |
||||
// Key returns pair's key.
|
||||
Key() string |
||||
// Value returns pair's value.
|
||||
Value() string |
||||
|
||||
// MustString returns the value's string representation
|
||||
// If empty, then it returns the given default.
|
||||
MustString(defaultVal string) string |
||||
// MustBool returns the value's boolean representation
|
||||
// Otherwise returns the given default.
|
||||
MustBool(defaultVal bool) bool |
||||
// MustDuration returns the value's time.Duration
|
||||
// representation. Otherwise returns the given default.
|
||||
MustDuration(defaultVal time.Duration) time.Duration |
||||
} |
||||
|
||||
// ReloadHandler defines the expected behaviour from a
|
||||
// service that have support for configuration reloads.
|
||||
type ReloadHandler interface { |
||||
// Reload handles reloading of configuration changes.
|
||||
Reload(section Section) error |
||||
|
||||
// Validate validates the configuration, if the validation
|
||||
// fails the configuration will not be updated neither reloaded.
|
||||
Validate(section Section) error |
||||
} |
||||
|
||||
type SettingsBag map[string]map[string]string |
||||
type SettingsRemovals map[string][]string |
||||
|
||||
type OSSImpl struct { |
||||
Cfg *Cfg `inject:""` |
||||
} |
||||
|
||||
func (o OSSImpl) Init() error { |
||||
return nil |
||||
} |
||||
|
||||
func (OSSImpl) Update(SettingsBag, SettingsRemovals) error { |
||||
return errors.New("oss settings provider do not have support for settings updates") |
||||
} |
||||
|
||||
func (o *OSSImpl) KeyValue(section, key string) KeyValue { |
||||
return o.Section(section).KeyValue(key) |
||||
} |
||||
|
||||
func (o *OSSImpl) Section(section string) Section { |
||||
return §ionImpl{section: o.Cfg.Raw.Section(section)} |
||||
} |
||||
|
||||
func (OSSImpl) RegisterReloadHandler(string, ReloadHandler) {} |
||||
|
||||
type keyValImpl struct { |
||||
key *ini.Key |
||||
} |
||||
|
||||
func (k *keyValImpl) Key() string { |
||||
return k.key.Name() |
||||
} |
||||
|
||||
func (k *keyValImpl) Value() string { |
||||
return k.key.Value() |
||||
} |
||||
|
||||
func (k *keyValImpl) MustString(defaultVal string) string { |
||||
return k.key.MustString(defaultVal) |
||||
} |
||||
|
||||
func (k *keyValImpl) MustBool(defaultVal bool) bool { |
||||
return k.key.MustBool(defaultVal) |
||||
} |
||||
|
||||
func (k *keyValImpl) MustDuration(defaultVal time.Duration) time.Duration { |
||||
return k.key.MustDuration(defaultVal) |
||||
} |
||||
|
||||
type sectionImpl struct { |
||||
section *ini.Section |
||||
} |
||||
|
||||
func (s *sectionImpl) KeyValue(key string) KeyValue { |
||||
return &keyValImpl{s.section.Key(key)} |
||||
} |
Loading…
Reference in new issue