config

package
v1.6.28 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 2, 2024 License: GPL-3.0 Imports: 29 Imported by: 0

Documentation

Overview

Package config provides a versatile configuration management system.

Index

Constants

View Source
const (
	ExpertiseLevelUser      ExpertiseLevel = 0
	ExpertiseLevelExpert    ExpertiseLevel = 1
	ExpertiseLevelDeveloper ExpertiseLevel = 2

	ExpertiseLevelNameUser      = "user"
	ExpertiseLevelNameExpert    = "expert"
	ExpertiseLevelNameDeveloper = "developer"
)

Expertise Level constants.

View Source
const (
	// DisplayHintAnnotation provides a hint for the user
	// interface on how to render an option.
	// The value of DisplayHintAnnotation is expected to
	// be a string. See DisplayHintXXXX constants below
	// for a list of well-known display hint annotations.
	DisplayHintAnnotation = "safing/portbase:ui:display-hint"
	// DisplayOrderAnnotation provides a hint for the user
	// interface in which order settings should be displayed.
	// The value of DisplayOrderAnnotations is expected to be
	// an number (int).
	DisplayOrderAnnotation = "safing/portbase:ui:order"
	// UnitAnnotations defines the SI unit of an option (if any).
	UnitAnnotation = "safing/portbase:ui:unit"
	// CategoryAnnotations can provide an additional category
	// to each settings. This category can be used by a user
	// interface to group certain options together.
	// User interfaces should treat a CategoryAnnotation, if
	// supported, with higher priority as a DisplayOrderAnnotation.
	CategoryAnnotation = "safing/portbase:ui:category"
	// SubsystemAnnotation can be used to mark an option as part
	// of a module subsystem.
	SubsystemAnnotation = "safing/portbase:module:subsystem"
	// StackableAnnotation can be set on configuration options that
	// stack on top of the default (or otherwise related) options.
	// The value of StackableAnnotaiton is expected to be a boolean but
	// may be extended to hold references to other options in the
	// future.
	StackableAnnotation = "safing/portbase:options:stackable"
	// RestartPendingAnnotation is automatically set on a configuration option
	// that requires a restart and has been changed.
	// The value must always be a boolean with value "true".
	RestartPendingAnnotation = "safing/portbase:options:restart-pending"
	// QuickSettingAnnotation can be used to add quick settings to
	// a configuration option. A quick setting can support the user
	// by switching between pre-configured values.
	// The type of a quick-setting annotation is []QuickSetting or QuickSetting.
	QuickSettingsAnnotation = "safing/portbase:ui:quick-setting"
	// RequiresAnnotation can be used to mark another option as a
	// requirement. The type of RequiresAnnotation is []ValueRequirement
	// or ValueRequirement.
	RequiresAnnotation = "safing/portbase:config:requires"
	// RequiresFeatureIDAnnotation can be used to mark a setting as only available
	// when the user has a certain feature ID in the subscription plan.
	// The type is []string or string.
	RequiresFeatureIDAnnotation = "safing/portmaster:ui:config:requires-feature"
	// SettablePerAppAnnotation can be used to mark a setting as settable per-app and
	// is a boolean.
	SettablePerAppAnnotation = "safing/portmaster:settable-per-app"
	// RequiresUIReloadAnnotation can be used to inform the UI that changing the value
	// of the annotated setting requires a full reload of the user interface.
	// The value of this annotation does not matter as the sole presence of
	// the annotation key is enough. Though, users are advised to set the value
	// of this annotation to true.
	RequiresUIReloadAnnotation = "safing/portmaster:ui:requires-reload"
)

Well known annotations defined by this package.

View Source
const (
	// QuickReplace replaces the current setting with the one from
	// the quick setting.
	QuickReplace = QuickSettingsAction("replace")
	// QuickMergeTop merges the value of the quick setting with the
	// already configured one adding new values on the top. Merging
	// is only supported for OptTypeStringArray.
	QuickMergeTop = QuickSettingsAction("merge-top")
	// QuickMergeBottom merges the value of the quick setting with the
	// already configured one adding new values at the bottom. Merging
	// is only supported for OptTypeStringArray.
	QuickMergeBottom = QuickSettingsAction("merge-bottom")
)
View Source
const (
	// DisplayHintOneOf is used to mark an option
	// as a "select"-style option. That is, only one of
	// the supported values may be set. This option makes
	// only sense together with the PossibleValues property
	// of Option.
	DisplayHintOneOf = "one-of"
	// DisplayHintOrdered is used to mark a list option as ordered.
	// That is, the order of items is important and a user interface
	// is encouraged to provide the user with re-ordering support
	// (like drag'n'drop).
	DisplayHintOrdered = "ordered"
	// DisplayHintFilePicker is used to mark the option as being a file, which
	// should give the option to use a file picker to select a local file from disk.
	DisplayHintFilePicker = "file-picker"
)

Values for the DisplayHintAnnotation.

View Source
const (
	ReleaseLevelStable       ReleaseLevel = 0
	ReleaseLevelBeta         ReleaseLevel = 1
	ReleaseLevelExperimental ReleaseLevel = 2

	ReleaseLevelNameStable       = "stable"
	ReleaseLevelNameBeta         = "beta"
	ReleaseLevelNameExperimental = "experimental"
)

Release Level constants.

View Source
const ChangeEvent = "config change"

ChangeEvent is the name of the config change event.

Variables

View Source
var (
	CfgDevModeKey = "core/devMode"

	CfgLogLevel = "core/log/level"
)

Configuration Keys.

View Source
var (
	// ErrInvalidJSON is returned by SetConfig and SetDefaultConfig if they receive invalid json.
	ErrInvalidJSON = errors.New("json string invalid")

	// ErrInvalidOptionType is returned by SetConfigOption and SetDefaultConfigOption if given an unsupported option type.
	ErrInvalidOptionType = errors.New("invalid option value type")
)
View Source
var Concurrent = &safe{}

Concurrent makes concurrency safe get methods available.

Functions

func AddToDebugInfo

func AddToDebugInfo(di *debug.Info)

AddToDebugInfo adds all changed global config options to the given debug.Info.

func CleanFlattenedConfig

func CleanFlattenedConfig(flattenedConfig map[string]interface{})

CleanFlattenedConfig removes all inexistent configuration options from the given flattened config map.

func CleanHierarchicalConfig

func CleanHierarchicalConfig(config map[string]interface{})

CleanHierarchicalConfig removes all inexistent configuration options from the given hierarchical config map.

func Expand

func Expand(flattenedConfig map[string]interface{}) (config map[string]interface{})

Expand returns a hierarchical copy of the given flattened config.

func Flatten

func Flatten(config map[string]interface{}) (flattenedConfig map[string]interface{})

Flatten returns a flattened copy of the given hierarchical config.

func ForEachOption

func ForEachOption(fn func(opt *Option) error) error

ForEachOption calls fn for each defined option. If fn returns and error the iteration is stopped and the error is returned. Note that ForEachOption does not guarantee a stable order of iteration between multiple calles. ForEachOption does NOT lock opt when calling fn.

func GetActiveConfigValues

func GetActiveConfigValues() map[string]interface{}

GetActiveConfigValues returns a map with the active config values.

func GetExpertiseLevel

func GetExpertiseLevel() uint8

GetExpertiseLevel returns the current active expertise level.

func InitializeUnitTestDataroot

func InitializeUnitTestDataroot(testName string) (string, error)

InitializeUnitTestDataroot initializes a new random tmp directory for running tests.

func JSONToMap

func JSONToMap(jsonData []byte) (map[string]interface{}, error)

JSONToMap parses and flattens a hierarchical json object.

func MapToJSON

func MapToJSON(config map[string]interface{}) ([]byte, error)

MapToJSON expands a flattened map and returns it as json.

func PutValueIntoHierarchicalConfig

func PutValueIntoHierarchicalConfig(config map[string]interface{}, key string, value interface{})

PutValueIntoHierarchicalConfig injects a configuration entry into an hierarchical config map. Conflicting entries will be replaced.

func Register

func Register(option *Option) error

Register registers a new configuration option.

func SaveConfig

func SaveConfig() error

SaveConfig saves the current configuration to file. It will acquire a read-lock on the global options registry lock and must lock each option!

func SetConfigOption

func SetConfigOption(key string, value any) error

SetConfigOption sets a single value in the (prioritized) user defined config.

func SetDataRoot

func SetDataRoot(root *utils.DirStructure)

SetDataRoot sets the data root from which the updates module derives its paths.

func SetDefaultConfigOption

func SetDefaultConfigOption(key string, value interface{}) error

SetDefaultConfigOption sets a single value in the (fallback) default config.

Types

type Annotations

type Annotations map[string]interface{}

Annotations can be attached to configuration options to provide hints for user interfaces or other systems working or setting configuration options. Annotation keys should follow the below format to ensure future well-known annotation additions do not conflict with vendor/product/package specific annoations.

Format: <vendor/package>:<scope>:<identifier> //.

type BoolOption

type BoolOption func() bool

BoolOption defines the returned function by GetAsBool.

func GetAsBool

func GetAsBool(name string, fallback bool) BoolOption

GetAsBool returns a function that returns the wanted int with high performance.

type Config

type Config struct {
	EventConfigChange *mgr.EventMgr[struct{}]
	// contains filtered or unexported fields
}

Config provides configuration mgmt.

func New

func New(instance instance) (*Config, error)

New returns a new Config module.

func (*Config) Manager

func (u *Config) Manager() *mgr.Manager

Manager returns the module's manager.

func (*Config) Start

func (u *Config) Start() error

Start starts the module.

func (*Config) Stop

func (u *Config) Stop() error

Stop stops the module.

type ExpertiseLevel

type ExpertiseLevel uint8

ExpertiseLevel allows to group settings by user expertise. It's useful if complex or technical settings should be hidden from the average user while still allowing experts and developers to change deep configuration settings.

type IntOption

type IntOption func() int64

IntOption defines the returned function by GetAsInt.

func GetAsInt

func GetAsInt(name string, fallback int64) IntOption

GetAsInt returns a function that returns the wanted int with high performance.

type MigrationFunc

type MigrationFunc func(option *Option, value any) any

MigrationFunc is a function that migrates a config option value.

type Option

type Option struct {
	sync.Mutex
	// Name holds the name of the configuration options.
	// It should be human readable and is mainly used for
	// presentation purposes.
	// Name is considered immutable after the option has
	// been created.
	Name string
	// Key holds the database path for the option. It should
	// follow the path format `category/sub/key`.
	// Key is considered immutable after the option has
	// been created.
	Key string
	// Description holds a human readable description of the
	// option and what is does. The description should be short.
	// Use the Help property for a longer support text.
	// Description is considered immutable after the option has
	// been created.
	Description string
	// Help may hold a long version of the description providing
	// assistance with the configuration option.
	// Help is considered immutable after the option has
	// been created.
	Help string
	// Sensitive signifies that the configuration values may contain sensitive
	// content, such as authentication keys.
	Sensitive bool
	// OptType defines the type of the option.
	// OptType is considered immutable after the option has
	// been created.
	OptType OptionType
	// ExpertiseLevel can be used to set the required expertise
	// level for the option to be displayed to a user.
	// ExpertiseLevel is considered immutable after the option has
	// been created.
	ExpertiseLevel ExpertiseLevel
	// ReleaseLevel is used to mark the stability of the option.
	// ReleaseLevel is considered immutable after the option has
	// been created.
	ReleaseLevel ReleaseLevel
	// RequiresRestart should be set to true if a modification of
	// the options value requires a restart of the whole application
	// to take effect.
	// RequiresRestart is considered immutable after the option has
	// been created.
	RequiresRestart bool
	// DefaultValue holds the default value of the option. Note that
	// this value can be overwritten during runtime (see activeDefaultValue
	// and activeFallbackValue).
	// DefaultValue is considered immutable after the option has
	// been created.
	DefaultValue interface{}
	// ValidationRegex may contain a regular expression used to validate
	// the value of option. If the option type is set to OptTypeStringArray
	// the validation regex is applied to all entries of the string slice.
	// Note that it is recommended to keep the validation regex simple so
	// it can also be used in other languages (mainly JavaScript) to provide
	// a better user-experience by pre-validating the expression.
	// ValidationRegex is considered immutable after the option has
	// been created.
	ValidationRegex string
	// ValidationFunc may contain a function to validate more complex values.
	// The error is returned beyond the scope of this package and may be
	// displayed to a user.
	ValidationFunc func(value interface{}) error `json:"-"`
	// PossibleValues may be set to a slice of values that are allowed
	// for this configuration setting. Note that PossibleValues makes most
	// sense when ExternalOptType is set to HintOneOf
	// PossibleValues is considered immutable after the option has
	// been created.
	PossibleValues []PossibleValue `json:",omitempty"`
	// Annotations adds additional annotations to the configuration options.
	// See documentation of Annotations for more information.
	// Annotations is considered mutable and setting/reading annotation keys
	// must be performed while the option is locked.
	Annotations Annotations
	// Migrations holds migration functions that are given the raw option value
	// before any validation is run. The returned value is then used.
	Migrations []MigrationFunc `json:"-"`
	// contains filtered or unexported fields
}

Option describes a configuration option.

func ExportOptions

func ExportOptions() []*Option

ExportOptions exports the registered options. The returned data must be treated as immutable. The data does not include the current active or default settings.

func GetOption

func GetOption(name string) (*Option, error)

GetOption returns the option with name or an error if the option does not exist. The caller should lock the returned option itself for further processing.

func (*Option) AddAnnotation

func (option *Option) AddAnnotation(key string, value interface{})

AddAnnotation adds the annotation key to option if it's not already set.

func (*Option) AnnotationEquals

func (option *Option) AnnotationEquals(key string, value any) bool

AnnotationEquals returns whether the annotation of the given key matches the given value.

func (*Option) Export

func (option *Option) Export() (record.Record, error)

Export expors an option to a Record.

func (*Option) GetAnnotation

func (option *Option) GetAnnotation(key string) (interface{}, bool)

GetAnnotation returns the value of the annotation key.

func (*Option) IsSetByUser

func (option *Option) IsSetByUser() bool

IsSetByUser returns whether the option has been set by the user.

func (*Option) SetAnnotation

func (option *Option) SetAnnotation(key string, value interface{})

SetAnnotation sets the value of the annotation key overwritting an existing value if required.

func (*Option) UserValue

func (option *Option) UserValue() any

UserValue returns the value set by the user or nil if the value has not been changed from the default.

func (*Option) ValidateValue

func (option *Option) ValidateValue(value any) error

ValidateValue checks if the given value is valid for the option.

type OptionType

type OptionType uint8

OptionType defines the value type of an option.

const (
	OptTypeString      OptionType = 1
	OptTypeStringArray OptionType = 2
	OptTypeInt         OptionType = 3
	OptTypeBool        OptionType = 4
)

Various attribute options. Use ExternalOptType for extended types in the frontend.

type Perspective

type Perspective struct {
	// contains filtered or unexported fields
}

Perspective is a view on configuration data without interfering with the configuration system.

func NewPerspective

func NewPerspective(config map[string]interface{}) (*Perspective, error)

NewPerspective parses the given config and returns it as a new perspective.

func (*Perspective) GetAsBool

func (p *Perspective) GetAsBool(name string) (value bool, ok bool)

GetAsBool returns a function that returns the wanted int with high performance.

func (*Perspective) GetAsInt

func (p *Perspective) GetAsInt(name string) (value int64, ok bool)

GetAsInt returns a function that returns the wanted int with high performance.

func (*Perspective) GetAsString

func (p *Perspective) GetAsString(name string) (value string, ok bool)

GetAsString returns a function that returns the wanted string with high performance.

func (*Perspective) GetAsStringArray

func (p *Perspective) GetAsStringArray(name string) (value []string, ok bool)

GetAsStringArray returns a function that returns the wanted string with high performance.

func (*Perspective) Has

func (p *Perspective) Has(name string) bool

Has returns whether the given option is set in the perspective.

type PossibleValue

type PossibleValue struct {
	// Name is a human readable name of the option.
	Name string
	// Description is a human readable description of
	// this value.
	Description string
	// Value is the actual value of the option. The type
	// must match the option's value type.
	Value interface{}
}

PossibleValue defines a value that is possible for a configuration setting.

type QuickSetting

type QuickSetting struct {
	// Name is the name of the quick setting.
	Name string

	// Value is the value that the quick-setting configures. It must match
	// the expected value type of the annotated option.
	Value interface{}

	// Action defines the action of the quick setting.
	Action QuickSettingsAction
}

QuickSetting defines a quick setting for a configuration option and should be used together with the QuickSettingsAnnotation.

type QuickSettingsAction

type QuickSettingsAction string

QuickSettingsAction defines the action of a quick setting.

type ReleaseLevel

type ReleaseLevel uint8

ReleaseLevel is used to define the maturity of a configuration setting.

type StorageInterface

type StorageInterface struct {
	storage.InjectBase
}

StorageInterface provices a storage.Interface to the configuration manager.

func (*StorageInterface) Delete

func (s *StorageInterface) Delete(key string) error

Delete deletes a record from the database.

func (*StorageInterface) Get

func (s *StorageInterface) Get(key string) (record.Record, error)

Get returns a database record.

func (*StorageInterface) Put

Put stores a record in the database.

func (*StorageInterface) Query

func (s *StorageInterface) Query(q *query.Query, local, internal bool) (*iterator.Iterator, error)

Query returns a an iterator for the supplied query.

func (*StorageInterface) ReadOnly

func (s *StorageInterface) ReadOnly() bool

ReadOnly returns whether the database is read only.

type StringArrayOption

type StringArrayOption func() []string

StringArrayOption defines the returned function by GetAsStringArray.

func GetAsStringArray

func GetAsStringArray(name string, fallback []string) StringArrayOption

GetAsStringArray returns a function that returns the wanted string with high performance.

type StringOption

type StringOption func() string

StringOption defines the returned function by GetAsString.

func GetAsString

func GetAsString(name string, fallback string) StringOption

GetAsString returns a function that returns the wanted string with high performance.

type ValidationError

type ValidationError struct {
	Option *Option
	Err    error
}

ValidationError error holds details about a config option value validation error.

func GetLoadedConfigValidationErrors

func GetLoadedConfigValidationErrors() []*ValidationError

GetLoadedConfigValidationErrors returns the encountered validation errors from the last time loading config from disk.

func ReplaceConfig

func ReplaceConfig(newValues map[string]interface{}) (validationErrors []*ValidationError, requiresRestart bool)

ReplaceConfig sets the (prioritized) user defined config.

func ReplaceDefaultConfig

func ReplaceDefaultConfig(newValues map[string]interface{}) (validationErrors []*ValidationError, requiresRestart bool)

ReplaceDefaultConfig sets the (fallback) default config.

func ValidateConfig

func ValidateConfig(newValues map[string]interface{}) (validationErrors []*ValidationError, requiresRestart bool, containsUnknown bool)

ValidateConfig validates the given configuration and returns all validation errors as well as whether the given configuration contains unknown keys.

func (*ValidationError) Error

func (ve *ValidationError) Error() string

Error returns the formatted error.

func (*ValidationError) Unwrap

func (ve *ValidationError) Unwrap() error

Unwrap returns the wrapped error.

type ValidityFlag

type ValidityFlag struct {
	// contains filtered or unexported fields
}

ValidityFlag is a flag that signifies if the configuration has been changed. It is not safe for concurrent use.

func NewValidityFlag

func NewValidityFlag() *ValidityFlag

NewValidityFlag returns a flag that signifies if the configuration has been changed. It always starts out as invalid. Refresh to start with the current value.

func (*ValidityFlag) IsValid

func (vf *ValidityFlag) IsValid() bool

IsValid returns if the configuration is still valid.

func (*ValidityFlag) Refresh

func (vf *ValidityFlag) Refresh()

Refresh refreshes the flag and makes it reusable.

type ValueRequirement

type ValueRequirement struct {
	// Key is the key of the configuration option that is required.
	Key string

	// Value that is required.
	Value interface{}
}

ValueRequirement defines a requirement on another configuration option.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL