Documentation ¶
Overview ¶
Package config, abbrev. cfg, handles the configuration and its scopes.
A configuration holds many path.Paths which contains a route, a scope and a scope ID.
A route is defined as a minimum 3 level deep string separated by a slash. For example catalog/product/enable_flat.
ScopePerm are default, website, group and store. Scope IDs are stored in the core_website, core_group or core_store tables for M1 and store_website, store_group and store for M2.
Underlying storage can be a simple in memory map (default), MySQL table core_config_data itself (package config/db) or etcd (package config/etcd) or consul (package todo) or ...
If you use any other configuration storage engine besides config/db package all values gets bi-directional automatically synchronized (todo).
Elements ¶
The package config/element contains more detailed information.
Scope Values ¶
To get a value from the configuration Service via any type method you have to provide a path.Path. If you use the ScopedGetter via function makeScoped() you can only provide a path.Route to the type methods String(), Int(), Float64(), etc.
The examples show the overall best practices.
Package cfgpath handles the configuration paths.
It contains two main types: Path and Route:
+-------+ +-----+ +----------+ +-----+ +----------------+ | | | | | | | | | | | Scope | | / | | Scope ID | | / | | Route/to/Value | | | | | | | | | | | +-------+ +-----+ +----------+ +-----+ +----------------+ + + + | | | | <--------------+ Path +-----------------------------> | | | | + + <- Route ----> +
Scope ¶
A scope can only be default, websites or stores. Those three strings are defined by constants in package store/scope.
Scope ID ¶
Refers to the database auto increment ID of one of the tables core_website and core_store for M1 and store_website plus store for M2.
Type Path ¶
A Path contains always the scope, its scope ID and the route. If scope and ID haven't been provided they fall back to scope "default" and ID zero (0). Configuration paths are mainly used in table core_config_data.
Type Route ¶
A route contains bytes and does not know anything about a scope or an ID. In the majority of use cases a route contains three parts to package config/element types for building a hierarchical tree structure:
element.Section.ID / element.Group.ID / element.Field.ID
To add little bit more confusion: A route can either be a short one like aa/bb/cc or a fully qualified path like
scope/scopeID/element.Section.ID/element.Group.ID/element.Field.ID
But the route always consists of a minimum of three parts.
A route can have only three groups of [a-zA-Z0-9_] characters split by '/'. The limitation to [a-zA-Z0-9_] is a M1/M2 thing and can be maybe later removed. Minimal length per part 2 characters. Case sensitive.
The route parts are used as an ID in element.Section, element.Group and element.Field types. See following text.
The following diagram shows the tree structure:
+---------+ | Section | +---------+ | | +-------+ +-->+ Group | | +-------+ | | | | +--------+ | +--->+ Field | | | +--------+ | | | | +--------+ | +--->+ Field | | | +--------+ | | | | +--------+ | +--->+ Field | | +--------+ | | +-------+ +-->+ Group | | +-------+ | | | | +--------+ | +--->+ Field | | | +--------+ | | | | +--------+ | +--->+ Field | | | +--------+ | | | | +--------+ | +--->+ Field | | +--------+ | http://asciiflow.com/
The three elements Section, Group and Field represents front-end configuration fields and more important default values and their permissions. A permission is of type scope.Perm and defines which of elements in which scope can be shown.
Those three elements represents the tree in function NewConfigStructure() which can be found in any package.
Unclear: Your app which includes the cs must merge all "PackageConfiguration"s into a single slice. You should submit all default values (interface config.Sectioner) to the config.Service.ApplyDefaults() function.
The JSON encoding of the three elements Section, Group and Field are intended to use on the backend REST API and for debugging and testing. Only used in non performance critical parts.package config
Index ¶
- Constants
- func MakeEvent(name string) (event uint8, err error)
- type FakeService
- type FakeWrite
- type Field
- type FieldMeta
- type FieldType
- type Fields
- type Group
- type Groups
- type LoadDataOption
- type MessageReceiver
- type Observer
- type ObserverRegisterer
- type Options
- type Path
- func (p *Path) AppendFQ(buf *bytes.Buffer) error
- func (p Path) Bind(s scope.TypeID) *Path
- func (p Path) BindDefault() *Path
- func (p Path) BindStore(id int64) *Path
- func (p Path) BindWebsite(id int64) *Path
- func (p *Path) Equal(b *Path) bool
- func (p *Path) EqualRoute(b *Path) bool
- func (p Path) ExpireIn(d time.Duration) Path
- func (p *Path) FQ() (string, error)
- func (p *Path) Hash64() uint64
- func (p *Path) Hash64ByLevel(depth int) uint64
- func (p *Path) IsEmpty() bool
- func (p *Path) IsValid() error
- func (p *Path) Level(depth int) (string, error)
- func (p *Path) MarshalBinary() (data []byte, err error)
- func (p *Path) MarshalText() (text []byte, err error)
- func (p Path) NewValue(data []byte) *Value
- func (p *Path) Parse(routeOrFQPath string) (err error)
- func (p *Path) ParseStrings(scp, id, route string) error
- func (p *Path) Part(pos int) (string, error)
- func (p *Path) Reset() *Path
- func (p *Path) RouteHasPrefix(route string) bool
- func (p *Path) ScopeRoute() (scope.TypeID, string)
- func (p *Path) Separators() (count int)
- func (p *Path) Split(ret ...string) (_ []string, err error)
- func (p *Path) String() string
- func (p *Path) UnmarshalBinary(data []byte) error
- func (p *Path) UnmarshalText(txt []byte) error
- func (p *Path) WithEnvSuffix() *Path
- type PathSlice
- type Route
- type Scoped
- type Scoper
- type Section
- type Sections
- func (ss Sections) Append(s ...*Section) Sections
- func (ss Sections) AppendFields(r string, fs ...*Field) (_ Sections, index int)
- func (ss Sections) Find(id string) (_ *Section, index int)
- func (ss Sections) FindField(r string) (_ *Field, index int)
- func (ss Sections) FindGroup(r string) (_ *Group, index int)
- func (ss Sections) Len() int
- func (ss Sections) Less(i, j int) bool
- func (ss Sections) Merge(sections ...*Section) Sections
- func (ss Sections) MergeMultiple(sSlices ...Sections) Sections
- func (ss Sections) Sort() Sections
- func (ss Sections) SortAll() Sections
- func (ss Sections) Swap(i, j int)
- func (ss Sections) TotalFields() (fs int)
- func (ss Sections) UpdateField(r string, nf *Field) (index int)
- func (ss Sections) Validate() error
- type Service
- func (s *Service) Close() error
- func (s *Service) DeregisterObserver(event uint8, route string) error
- func (s *Service) EnvName() string
- func (s *Service) Flush() error
- func (s *Service) Get(p *Path) (v *Value)
- func (s *Service) RegisterObserver(event uint8, route string, eo Observer) error
- func (s *Service) ReplaceEnvName(str string) string
- func (s *Service) Scoped(websiteID, storeID int64) Scoped
- func (s *Service) Set(p *Path, v []byte) (err error)
- func (s *Service) Subscribe(path string, mr MessageReceiver) (subscriptionID int, err error)
- func (s *Service) Unsubscribe(subscriptionID int) error
- type Setter
- type Storager
- type Subscriber
- type Value
- func (v *Value) Bool() (val bool, ok bool, err error)
- func (v *Value) CSV(ret ...[]string) (_ [][]string, err error)
- func (v *Value) ConstantTimeCompare(data []byte) bool
- func (v *Value) Duration() (d time.Duration, ok bool, err error)
- func (v *Value) Equal(v2 *Value) bool
- func (v *Value) EqualData(v2 *Value) bool
- func (v *Value) Error() string
- func (v *Value) Float64() (val float64, ok bool, err error)
- func (v *Value) Float64s(ret ...float64) (_ []float64, err error)
- func (v *Value) Int() (val int, ok bool, err error)
- func (v *Value) Int64() (_ int64, ok bool, err error)
- func (v *Value) Int64s(ret ...int64) (_ []int64, err error)
- func (v *Value) Ints(ret ...int) (_ []int, err error)
- func (v *Value) IsEmpty() bool
- func (v *Value) IsEqual(d []byte) bool
- func (v *Value) IsValid() bool
- func (v *Value) Str() (_ string, ok bool, err error)
- func (v *Value) String() string
- func (v *Value) Strs(ret ...string) (_ []string, err error)
- func (v *Value) Time() (t time.Time, ok bool, err error)
- func (v *Value) Times(ret ...time.Time) (t []time.Time, err error)
- func (v *Value) Uint64() (_ uint64, ok bool, err error)
- func (v *Value) Uint64s(ret ...uint64) (_ []uint64, err error)
- func (v *Value) UnmarshalBinaryTo(tu encoding.BinaryUnmarshaler) error
- func (v *Value) UnmarshalTextTo(tu encoding.TextUnmarshaler) error
- func (v *Value) UnmarshalTo(fn func([]byte, interface{}) error, vPtr interface{}) (err error)
- func (v *Value) UnsafeBool() (val bool)
- func (v *Value) UnsafeDuration() (d time.Duration)
- func (v *Value) UnsafeFloat64() (val float64)
- func (v *Value) UnsafeInt() (val int)
- func (v *Value) UnsafeInt64() (val int64)
- func (v *Value) UnsafeStr() (s string)
- func (v *Value) UnsafeTime() (t time.Time)
- func (v *Value) UnsafeUint64() (val uint64)
- func (v *Value) WriteTo(w io.Writer) (n int64, err error)
Examples ¶
Constants ¶
const ( EventOnBeforeSet uint8 = iota // must start with zero EventOnAfterSet EventOnBeforeGet EventOnAfterGet )
Event constants defines where and when a specific blocking event gets dispatched. The concrete value of a constant may change without notice.
const CSVColumnSeparator = ','
CSVColumnSeparator separates CSV values. Default value.
const DefaultOSEnvVariableName = `CS_ENV`
DefaultOSEnvVariableName default name of the OS environment variable.
const EnvNamePlaceHolder = `{CS_ENV}`
EnvNamePlaceHolder replaces in a file name or pattern argument applied to a WithFiles, WithFile or WithGlob function with the current environment name of *config.Service. You can load environment dependent configuration files.
const PathLevels = 3
PathLevels defines how many parts are at least in a path. Like a/b/c for 3 parts. And 5 for a fully qualified path.
const PathSeparator = '/'
PathSeparator used in the database table core_config_data and in config.Service to separate the path parts.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type FakeService ¶
type FakeService struct { // GetFn can be set optionally. If set then Storage will be ignored. // Must return a guaranteed non-nil Value. GetFn func(p *Path) (v *Value) SubscribeFn func(string, MessageReceiver) (subscriptionID int, err error) SubscribeInvokes int32 // contains filtered or unexported fields }
FakeService used for testing. Contains functions which will be called in the appropriate methods of interface Getter. Field DB has precedence over the applied functions.
func NewFakeService ¶
func NewFakeService(s Storager) *FakeService
NewFakeService creates a new mocked Service for testing usage. Initializes a simple in memory key/value storage.
func (*FakeService) AllInvocations ¶
func (s *FakeService) AllInvocations() invocations
AllInvocations returns all called paths and increases the counter for duplicated paths.
func (*FakeService) Get ¶
func (s *FakeService) Get(p *Path) *Value
Get looks up a configuration value for a given path.
func (*FakeService) Invokes ¶
func (s *FakeService) Invokes() invocations
Invokes returns statistics about invocations
func (*FakeService) Scoped ¶
func (s *FakeService) Scoped(websiteID, storeID int64) Scoped
Scoped creates a new ScopedReader which uses the underlying mocked paths and values.
func (*FakeService) Subscribe ¶
func (s *FakeService) Subscribe(path string, mr MessageReceiver) (subscriptionID int, err error)
Subscribe returns the before applied SubscriptionID and SubscriptionErr Does not start any underlying Goroutines.
type FakeWrite ¶
type FakeWrite struct { // WriteError gets always returned by FakeWrite WriteError error // ArgPath will be set after calling write to export the config path. // Values you enter here will be overwritten when calling FakeWrite ArgPath string // ArgValue contains the written data ArgValue []byte }
FakeWrite used for testing when writing configuration values. deprecated no replacement
type Field ¶
type Field struct { // ID unique ID and NOT merged with others. 3rd and final part of the path. ID string // ConfigRoute if provided defines the storage path and overwrites the path from // section.id + group.id + field.id. ConfigRoute can be nil. ConfigRoute string `json:",omitempty"` // Type is used for the front end on how to display a Field Type FieldType `json:",omitempty"` // Label a short label of the field Label string `json:",omitempty"` // Comment can contain HTML Comment string `json:",omitempty"` // Tooltip used for frontend and can contain HTML Tooltip string `json:",omitempty"` // SortOrder in ascending order SortOrder int `json:",omitempty"` // Visible used for configuration settings which are not exposed to the user. Visible bool `json:",omitempty"` // CanBeEmpty only used in HTML forms for multiselect fields CanBeEmpty bool `json:",omitempty"` // Scopes defines the max allowed scope. Some paths or values can only act // on default, website or store scope. So perm checks if the provided // path has a scope equal or lower than defined in perm. Scopes scope.Perm `json:",omitempty"` // Default can contain any default config value: float64, int64, string, // bool. An empty string is equal to NULL. A default gets requests if the // value for a path cannot be retrieved from Level1 or Level2 storage. Default string `json:",omitempty"` }
Field contains the final path element of a configuration. Includes several options.
type FieldMeta ¶
type FieldMeta struct { Events [eventMaxCount]observers // Route defines the route or storage key, e.g.: customer/address/prefix_options Route string // WriteScopePerm sets the permission to allow setting values to this route. // For example WriteScopePerm equals scope.PermStore can be set from // default, website and store. If you restrict WriteScopePerm to // scope.PermDefault, the route and its value can only be set from default // but not from websites or stores. It is only allowed to set WriteScopePerm // when ScopeID is zero or scope.DefaultTypeID. WriteScopePerm scope.Perm // ScopeID defines the scope ID for which a default value is valid. Scope // type can only contain three scopes (default,websites or stores). ID // relates to the corresponding website or store ID. ScopeID scope.TypeID Default string DefaultValid bool // contains filtered or unexported fields }
FieldMeta sets meta data for a field into the config.Service object. The meta data defines scope access restrictions and default values for different scopes. Intermediate type for function WithFieldMeta
type FieldType ¶
type FieldType uint8
FieldType used in constants to define the frontend and input type
const ( TypeButton FieldType = iota + 1 // must be + 1 because 0 is not set TypeCustom TypeLabel TypeHidden TypeImage TypeObscure TypeMultiselect TypeSelect TypeText TypeTextarea TypeTime TypeDuration TypeZMaximum )
Type* defines the type of the front end user input/display form
func (FieldType) MarshalJSON ¶
MarshalJSON implements marshaling into a human readable string. @todo UnMarshal
type Fields ¶
type Fields []*Field
Fields contains a set of Fields, the final configuration value.
func (Fields) Find ¶
Find returns a Field pointer or index is -1 if field not found. Route must be a single part. E.g. if you have path "a/b/c" route would be in this case "c". 2nd argument int contains the slice index of the field.
type Group ¶
type Group struct { // ID unique ID and merged with others. 2nd part of the path. ID string Label string `json:",omitempty"` Comment string `json:",omitempty"` // Scopes: bit value eg: showInDefault="1" showInWebsite="1" showInStore="1" Scopes scope.Perm `json:",omitempty"` SortOrder int `json:",omitempty"` HelpURL string `json:",omitempty"` MoreURL string `json:",omitempty"` DemoLink string `json:",omitempty"` Fields Fields `json:",omitempty"` }
Group defines the layout of a group containing multiple Fields.
type Groups ¶
type Groups []*Group
Groups contains a set of Groups.
func (Groups) Find ¶
Find returns a Group pointer or index -1 if group not found. Route must be a single part. E.g. if you have path "a/b/c" route would be in this case "b".
type LoadDataOption ¶
type LoadDataOption struct {
// contains filtered or unexported fields
}
LoadDataOption allows other storage backends to pump their data into the config.Service during or after initialization via an OS signal and hot reloading.
func MakeLoadDataOption ¶
func MakeLoadDataOption(fn func(*Service) error) LoadDataOption
MakeLoadDataOption a wrapper helper function.
func WithApplySections ¶
func WithApplySections(sections ...*Section) LoadDataOption
WithApplySections sets the default values and permissible scopes for specific routes. This function option cannot handle a default value for a specific website/store scope. Storage level and sort order are not supported. Because of using FieldMeta, it supports hierarchical fall back to the parent scope for default values.
func WithFieldMeta ¶
func WithFieldMeta(fms ...*FieldMeta) LoadDataOption
WithFieldMeta sets immutable default values and scope restrictions into the service for specific routes. Storage level and sort order are not supported. FieldMeta data gets only set once. Reloading is not possible. Synchronous version.
func WithFieldMetaGenerator ¶
func WithFieldMetaGenerator(fmGenerator func(*Service) (<-chan *FieldMeta, <-chan error)) LoadDataOption
WithFieldMetaGenerator sets immutable default values and scope restrictions into the service for specific routes. Storage level and sort order are not supported. FieldMeta data gets only set once. Reloading is not possible. Supports hierarchical fall back to the parent scope for default values. See cfgfile.WithLoadFieldMetaYAML to load this data via a YAML file. This functional options supports stream based processing. fmGenerator function must close both channels once the process finishes.
func (LoadDataOption) WithSortOrder ¶
func (o LoadDataOption) WithSortOrder(sortOrderPosition int) LoadDataOption
WithSortOrder sets the order/position while loading the data in config.Service.
func (LoadDataOption) WithUseStorageLevel ¶
func (o LoadDataOption) WithUseStorageLevel(level int) LoadDataOption
WithUseStorageLevel executes the current Load function in storage level one. Argument level can either be 1 or 2. Any other integer value falls back to 2, for now.
type MessageReceiver ¶
type MessageReceiver interface { // MessageConfig when a configuration value will be written this function // gets called to allow you to listen to changes. Path is never empty. Path // may contains up to three levels. For more details see the Subscriber // interface of this package. If an error will be returned, the subscriber // gets unsubscribed/removed. MessageConfig(Path) error }
MessageReceiver allows you to listen to write actions. The order of calling each subscriber is totally random. If a subscriber panics, it gets securely removed without crashing the whole system. This interface should be implemented in other packages. The Subscriber interface requires the MessageReceiver interface.
type Observer ¶
type Observer interface { // Observe must always return the rawData argument or an error. // Observer can transform and modify the raw data in any case. Observe(p Path, rawData []byte, found bool) (newRawData []byte, err error) }
Observer gets called when an event gets dispatched. Not all events support modifying the raw data argument. For example the EventOnAfterGet allows to decrypt encrypted data. Or check if some one is allowed to read or write a special path with its value. Or validate data for correctness.
type ObserverRegisterer ¶
type ObserverRegisterer interface { RegisterObserver(event uint8, route string, eo Observer) error DeregisterObserver(event uint8, route string) error }
ObserverRegisterer adds or removes observers for different events and theirs routes. Extracted for testability in other packages. Type *Service implements this interface.
type Options ¶
type Options struct { // Level1 defines a usually short lived cached like an LRU or TinyLFU or a // storage with un-resetble data (locked data). It can be set optionally. // Level1 only gets called for Set operation when a value is requested in // Level2 via Get. Level1 Storager Log log.Logger EnablePubSub bool // OSEnvVariableName loads a string from an applied environment variable to // use it as a prefix for the Path type and when loading configuration files // as part of their filename or path (see cfgfile.EnvNamePlaceHolder). For // example different payment gateways and access credentials for a payment // method on STAGING or PRODUCTION systems. OSEnvVariableName string // EnvName defines the current name of the environment directly instead of // loading it from an operating system environment variable. It gets used as // a prefix for the Path type or as part of the directory or filename when // loading configuration files (see cfgfile.EnvNamePlaceHolder). EnvName string // EnableHotReload if the Service receives an OS signal, it triggers a hot // reload of the cached functions of type LoadDataOption. Errors during hot // reloading do not trigger an exit of the config.Service. EnableHotReload bool // HotReloadSignals specifies custom signals to listen to. Defaults to // syscall.SIGUSR2 HotReloadSignals []os.Signal }
Options applies configurations to the NewService function. Used mainly by external packages for providing different storage engines.
type Path ¶
type Path struct { // ScopeID a route is bound to this Scope and its ID. ScopeID scope.TypeID // UseEnvSuffix if enabled the Path has environment awareness. An // environment comes from the *Service type and defines for example // PRODUCTION, TEST, CI or STAGING. The final path will use this suffix to // distinguish between the environments. Environment awareness should be // added to Paths for e.g. payment credentials or order export access data. // Paths which are marked for environment awareness must have stored their // values for each environment. For example: a route can be // carriers/dhl/password and an integration has three environments set: // PRD,TEST,DEV. The final paths for the default value would be: // default/0/carriers/dhl/password/PRD // default/0/carriers/dhl/password/TEST // default/0/carriers/dhl/password/DEV // The path for PRD can also be default/0/carriers/dhl/password when there // would be no OS environment variable present. UseEnvSuffix bool // Expires defines a time when a key becomes inactive and hence expires. The // expiration is only supported when writing a value via interface // Setter.Set. The same path can have different expiration dates and values. // This feature depends on the underlying storage engine. Expires time.Time // contains filtered or unexported fields }
Path represents a configuration path bound to a scope. A Path is not safe for concurrent use. Bind* method receivers always return a new copy of a path.
Example ¶
package main import ( "fmt" "github.com/corestoreio/pkg/config" "github.com/corestoreio/pkg/store/scope" ) func main() { p := config.MustNewPath("system/smtp/host") fmt.Println(p.String()) fmt.Println(p.BindWebsite(1).String()) // alternative way fmt.Println(p.BindWebsite(1).String()) fmt.Println(p.BindStore(3).String()) // alternative way fmt.Println(p.BindStore(3).String()) // Group is not supported and falls back to default fmt.Println(p.Bind(scope.Group.WithID(4)).String()) p, err := config.NewPath("system/smtp/host") if err != nil { fmt.Printf("%s\n", err) } fmt.Println(p.String()) routes := config.MustNewPath("dev/css/merge_css_files") rs, err := routes.Split() if err != nil { fmt.Printf("%s\n", err) } fmt.Println("dev/css/merge_css_files => ", rs[0], rs[1], rs[2]) }
Output: default/0/system/smtp/host websites/1/system/smtp/host websites/1/system/smtp/host stores/3/system/smtp/host stores/3/system/smtp/host default/0/system/smtp/host default/0/system/smtp/host dev/css/merge_css_files => dev css merge_css_files
func MustNewPath ¶
MustNewPath same as NewPath but panics on error.
func MustNewPathWithScope ¶
MustNewPathWithScope creates a new validate Path with a custom scope but panics on error. E.g. invalid path.
func NewPathWithScope ¶
NewPathWithScope creates a new validate Path with a custom scope.
func (Path) Bind ¶
Bind binds a path to a new scope with its scope ID. Returns a new Path pointer and does not apply the changes to the current Path. Fluent API design.
func (Path) BindDefault ¶
BindDefault binds a path to the default scope. Returns a new Path pointer and does not apply the changes to the current Path. Convenience helper function. Fluent API design.
func (Path) BindStore ¶
BindStore binds a path to a store scope and its ID. Returns a new Path pointer and does not apply the changes to the current Path. Convenience helper function. Fluent API design.
func (Path) BindWebsite ¶
BindWebsite binds a path to a website scope and its ID. Returns a new Path pointer and does not apply the changes to the current Path. Convenience helper function. Fluent API design.
func (*Path) EqualRoute ¶
EqualRoute compares only the route.
func (Path) ExpireIn ¶
ExpireIn sets the current time with the default time zone and adds the duration. It returns a copy of the path with the new expiration value.
func (*Path) FQ ¶
FQ returns the fully qualified route. Safe for further processing of the returned byte slice. If scope is equal to scope.DefaultID and ID is not zero then ID gets set to zero. Error behaviour: NotValid, Empty or WriteFailed
func (*Path) Hash64 ¶
Hash64 computes the HighwayHash-64 checksum of data. Returns zero in case of an error. Usage as map key.
func (*Path) Hash64ByLevel ¶
Hash64ByLevel same as Level() but returns a HighwayHash-64 checksum of data. Usage as map key.
func (*Path) IsValid ¶
IsValid checks for valid configuration path. Returns nil on success. Configuration path attribute can have only three groups of [a-zA-Z0-9_] characters split by '/'. Minimal length per part 2 characters. Case sensitive.
Error behaviour: NotValid or Empty
func (*Path) Level ¶
Level returns a hierarchical based route depending on the depth. The depth argument defines the depth of levels to be returned. Depth 1 will return the first part like "a", Depth 2 returns "a/b" Depth 3 returns "a/b/c" and so on. Level -1 gives you all available levels. Does generate a fully qualified path.
func (*Path) MarshalBinary ¶
MarshalBinary implements interface encoding.BinaryMarshaler.
func (*Path) MarshalText ¶
MarshalText implements interface encoding.TextMarshaler.
func (Path) NewValue ¶
NewValue creates a new value with an assigned path. Guarantees not to return nil.
func (*Path) Parse ¶
Parse takes a route or a fully qualified path and splits it into its parts with final validation. Input: stores/5/catalog/frontend/list_allow_all or just catalog/frontend/list_allow_all to use default scope.
=> scope: stores scopeID: 5 route: catalog/frontend/list_allow_all
Zero allocations to memory. Useful to reduce allocations by reusing Path pointer because it calls internally Reset.
func (*Path) ParseStrings ¶
ParseStrings parses the arguments into a valid path. scp must be a valid scope string as defined in stores/scope package. id must be a stringified uint value.
func (*Path) Part ¶
Part returns the route part on the desired position. The Route gets validated before extracting the part. Does not run Validate()
Have Route: general/single_store_mode/enabled Pos<1 => ErrIncorrectPosition Pos=1 => general Pos=2 => single_store_mode Pos=3 => enabled Pos>3 => ErrIncorrectPosition
The returned Route slice is owned by Path. For further modifications you must copy it via Route.Copy().
func (*Path) RouteHasPrefix ¶
RouteHasPrefix returns true if the Paths' route starts with the argument route
func (*Path) ScopeRoute ¶
ScopeRoute returns the assigned scope and its ID and the route.
func (*Path) Separators ¶
Separators returns the number of separators
func (*Path) Split ¶
Split splits the route into its three parts and appends it to the slice `ret`. Does not run Validate() Example:
routes := cfgpath.MakeRoute("aa/bb/cc") rs, err := routes.Split() rs[0].String() == "aa" rs[1].String() == "bb" rs[2].String() == "cc"
Error behaviour: NotValid
func (*Path) String ¶
String returns a fully qualified path. Errors get logged if debug mode is enabled. String starts with `[config] Error:` on error. Error behaviour: NotValid, Empty or WriteFailed
func (*Path) UnmarshalBinary ¶
UnmarshalBinary decodes input bytes into a valid Path. Implements encoding.BinaryUnmarshaler.
func (*Path) UnmarshalText ¶
UnmarshalText transforms the text into a route with performed validation checks. Implements encoding.TextUnmarshaler. Error behaviour: NotValid, Empty.
func (*Path) WithEnvSuffix ¶
WithEnvSuffix enables that this Path has environment awareness. An environment comes from the *Service type and defines for example PRODUCTION, TEST, CI or STAGING. The final path will use this prefix to distinguish between the environments. Environment awareness should be added to Paths for e.g. payment credentials or order export access data.
type PathSlice ¶
type PathSlice []*Path
PathSlice represents a collection of Paths
type Route ¶
type Route string
Route defines a string with at least two Separators denoting a route to the configuration value in a hierarchical manner. A Route does not contain any information about a scope. The purpose of Route should be to transfer a constant string later into a type Path.
func (Route) BindDefault ¶
BindDefault creates a new Path and binds it to the default scope.
func (Route) BindWebsite ¶
BindWebsite creates a new Path and binds it to a website scope and its ID.
func (Route) Separators ¶
Separators returns the number of separators
type Scoped ¶
type Scoped struct {
// contains filtered or unexported fields
}
Scoped is equal to Getter but not an interface and the underlying implementation takes care of providing the correct scope: default, website or store and bubbling up the scope chain from store -> website -> default if a value won't get found in the desired scope. The Path for each primitive type represents always a path like "section/group/element" without the scope string and scope ID.
To restrict bubbling up you can provide a second argument scope.Scope. You can restrict a configuration path to be only used with the default, website or store scope. See the examples. This second argument will mainly be used by the cfgmodel package to use a defined scope in a config.Structure. If you access the ScopedGetter from a store.Store, store.Website type the second argument must already be internally pre-filled.
WebsiteID and StoreID must be in a relation like enforced in the database tables via foreign keys. Empty storeID triggers the website scope. Empty websiteID and empty storeID are triggering the default scope.
func (Scoped) Get ¶
Get traverses through the scopes store->website->default to find a matching byte slice value. The argument `restrictUpTo` scope.Type restricts the bubbling. For example a path gets stored in all three scopes but argument `restrictUpTo` specifies only website scope, then the store scope will be ignored for querying. If argument `restrictUpTo` has been set to zero aka. scope.Absent, then all three scopes are considered for querying. Returns a guaranteed non-nil Value.
func (Scoped) ParentID ¶
ParentID tells you the parent underlying scope and its ID. Store falls back to website and website falls back to default.
type Scoper ¶
Scoper creates a hierarchy based configuration retriever based on website and its store ID. Scoper gets used in other packages to attach the config.Service type or mocked version of it.
type Section ¶
type Section struct { // ID unique ID and merged with others. 1st part of the path. ID string Label string `json:",omitempty"` // Scopes: bit value eg: showInDefault="1" showInWebsite="1" showInStore="1" // Scopes can contain multiple Scope but no more than Default, Website and // Store. Scopes scope.Perm `json:",omitempty"` SortOrder int `json:",omitempty"` // Resource TODO some kind of ACL if someone has the right to view,access and/or modify. Resource uint `json:",omitempty"` Groups Groups `json:",omitempty"` }
Section defines the layout for the configuration section which contains groups and fields. Thread safe for reading but not for modifying.
type Sections ¶
type Sections []*Section
Sections contains a set of Sections. Some nifty helper functions exists. Thread safe for reading. A section slice can be used in many goroutines. It must remain lock-free.
func MakeSections ¶
MakeSections wrapper function, for now.
func MakeSectionsMerged ¶
MakeSectionsMerged creates a new validated Sections with a three level configuration. Before validation, slices are all merged together. Panics if a path is redundant. Only use this function if your package elements really has duplicated entries.
func MakeSectionsValidated ¶
MakeSectionsValidated creates a new validated Sections with a three level configuration.
func MustMakeSectionsMerged ¶
MustMakeSectionsMerged same as MakeSectionsMerged but panics on error.
func MustMakeSectionsValidate ¶
MustMakeSectionsValidate same as MakeSectionsValidated but panics on error.
func (Sections) AppendFields ¶
AppendFields adds 0..n *Fields. Path must have at least two path parts like a/b more path parts gets ignored. Returns as index the new length of the FieldSlice or a negative value on error.
func (Sections) Find ¶
Find returns a Section pointer or -1 if section not found. Route must be a single part. E.g. if you have path "a/b/c" route would be in this case "a". 2nd return parameter contains the position of the Section within the Sections or -1 if not found.
func (Sections) FindField ¶
FindField searches for a field using all path segments. Route must have the format a/b/c. 2nd return parameter contains the position of the Field within the FieldSlice of a Section/Group or -1 if not found.
func (Sections) FindGroup ¶
FindGroup searches for a group using the first two path segments. Route must have the format a/b/c. 2nd return parameter contains the position of the Group within the GroupSlice of a Section or -1 if not found.
func (Sections) Merge ¶
Merge merges n Sections into the current slice. Behaviour for duplicates: Last item wins. Not thread safe.
func (Sections) MergeMultiple ¶
MergeMultiple merges n SectionSlices into the current slice. Behaviour for duplicates: Last item wins. Not thread safe.
func (Sections) TotalFields ¶
TotalFields calculates the total amount of all fields
func (Sections) UpdateField ¶
UpdateField searches for a field using all three path segments and updates the found field with the new field data. Returns the field position within the GroupSlice or a negative index in case a route part can't be found.
type Service ¶
Service main configuration provider. Please use the NewService() function. Safe for concurrent use. Allows multi level storage backend for e.g. LRU cache or immutable data. Hot reloading enables a devops engineer to apply new configuration changes via kill signal.
Example ¶
package main import ( "fmt" "github.com/corestoreio/pkg/config" "github.com/corestoreio/pkg/config/storage" ) func main() { // We focus here on type String() other primitive types are of course also available. p := config.MustNewPath("scope/test/string") // panics on incorrect argument. // Default storage engine with build-in in-memory map. // the NewService gets only instantiated once during app start up. configSrv := config.MustNewService(storage.NewMap(), config.Options{}) // now add some configuration values with different scopes. // normally these config values will be loaded from the core_config_data table // via function ApplyCoreConfigData() // The scope is default -> website (ID 3) -> group (ID 1) -> store (ID 2). // The IDs are picked randomly here. Group config values are officially not // supported, but we do ;-) // scope default: if err := configSrv.Set(p, []byte("DefaultGopher")); err != nil { fmt.Printf("Write Error: %s", err) return } // scope website. The number 3 is made up and comes usually from DB table // (M1) core_website or (M2) store_website. if err := configSrv.Set(p.BindWebsite(3), []byte("WebsiteGopher")); err != nil { fmt.Printf("Write Error: %s", err) return } // scope store. The number 2 is made up and comes usually from DB table // (M1) core_store or (M2) store. if err := configSrv.Set(p.BindStore(2), []byte("StoreGopher")); err != nil { fmt.Printf("Write Error: %s", err) return } // Default Scope1 val, ok, err := configSrv.Get(p.BindDefault()).Str() if err != nil { fmt.Printf("srvString Error: %s", err) return } fmt.Println("Scope1:", ok, val) // Website Scope2 val, ok, err = configSrv.Get(p.BindWebsite(3)).Str() if err != nil { fmt.Printf("srvString Error: %s", err) return } fmt.Println("Scope2:", ok, val) // Store Scope3 val, ok, err = configSrv.Get(p.BindStore(2)).Str() if err != nil { fmt.Printf("srvString Error: %s", err) return } fmt.Println("Scope3:", ok, val) // Store Scope4 _, ok, err = configSrv.Get(p.BindStore(3)).Str() // different scope ID if err != nil { fmt.Printf("Scope4a: srvString Error: %s\n", err) fmt.Printf("Scope4b: srvString Error: %v\n", err) // Use %+v to show the full route! :-) } fmt.Printf("Scope4: Is Key ok: %t\n", ok) }
Output: Scope1: true DefaultGopher Scope2: true WebsiteGopher Scope3: true StoreGopher Scope4: Is Key ok: false
func MustNewService ¶
func MustNewService(level2 Storager, o Options, fns ...LoadDataOption) *Service
MustNewService same as NewService but panics on error. Use only in testing or during boot process.
func NewService ¶
func NewService(level2 Storager, o Options, fns ...LoadDataOption) (s *Service, err error)
NewService creates the main new configuration for all scopes: default, website and store. Default Storage is a simple map[string]interface{}. A new go routine will be startet for the publish and subscribe feature. Level2 is the required underlying data holding provider.
func (*Service) DeregisterObserver ¶
DeregisterObserver removes all observers for a specific route or route prefix. Event argument is one of the constants starting with `EventOn...`.
func (*Service) Flush ¶
Flush flushes the internal caches. Write operation also flushes the entry for the given key. If a Storage service implements
type flusher interface { Flush() error }
then it can flush its internal caches.
func (*Service) Get ¶
Get returns a configuration value from the Service, ignoring the scope hierarchy/fallback logic using a direct match. Safe for concurrent use. Example usage:
// Default Scope dp := config.MustNewPath("general/locale/timezone") // Website Scope // 3 for example comes from store_website database table ws := dp.Bind(scope.WebsiteID, 3) // Store Scope // 6 for example comes from store database table ss := p.Bind(scope.StoreID, 6)
It queries first the Level1 cache, if not found, then Level2. If the value cannot be found eventually it accesses the default configuration and tries to get the value. If path meta data has been set, it checks also the permission if a path is allowed to access a specific scope.
Returns a guaranteed non-nil value.
func (*Service) RegisterObserver ¶
RegisterObserver appends a blocking observer for a route or route prefix. Multiple observers can be added to a route. Event argument is one of the constants starting with `EventOn...`.
func (*Service) ReplaceEnvName ¶
ReplaceEnvName replaces the occurrence of the value of constant EnvNamePlaceHolder with the current configured environment name. If no environment name has been defined it returns the argument unchanged.
func (*Service) Scoped ¶
Scoped creates a new scope base configuration reader which has the implemented fall back hierarchy.
func (*Service) Set ¶
Set puts a value back into the Service. Safe for concurrent use. Example usage:
// Default Scope p, err := config.MakeByString("currency/option/base") // or use config.MustMakeByString( ... ) err := Write(p, "USD") // Website Scope // 3 for example comes from core_website/store_website database table err := Write(p.Bind(scope.WebsiteID, 3), "EUR") // Store Scope // 6 for example comes from core_store/store database table err := Write(p.Bind(scope.StoreID, 6), "CHF")
func (*Service) Subscribe ¶
func (s *Service) Subscribe(path string, mr MessageReceiver) (subscriptionID int, err error)
Subscribe adds an asynchronous Subscriber to be called when a write event happens. See interface Subscriber for a detailed description. Path can be any kind of level and can contain StrScope and Scope ID. Valid paths can be for example:
- StrScope/ID/currency/options/base
- StrScope/ID/currency/options
- StrScope/ID/currency
- currency/options/base
- currency/options
- currency
Events are running asynchronously.
func (*Service) Unsubscribe ¶
Unsubscribe removes a subscriber with a specific ID.
type Setter ¶
type Setter interface { // Write writes a configuration entry and may return an error Set(p *Path, value []byte) error }
Setter thread safe storing of configuration values under different paths and scopes.
type Storager ¶
type Storager interface { // Set sets a key with a value and returns on success nil or // ErrKeyOverwritten, on failure any other error Setter // Get returns the raw value `v` on success and sets `found` to true // because the value has been found. If the value cannot be found for the // desired path, return value `found` must be false. A nil value `v` // indicates also a value and hence `found` is true, if found. Get(p *Path) (v []byte, found bool, err error) }
Storager is the underlying data storage for holding the keys and its values. Implementations can be spf13/viper or MySQL backed. Default Storager is a simple mutex protected in memory map[string]string. Storager must be safe for concurrent use.
type Subscriber ¶
type Subscriber interface { // Subscribe subscribes a MessageReceiver to a fully qualified path. Path // allows you to filter to which path or part of a path you would like to // listen. A path can be e.g. "system/smtp/host" to receive messages by // single host changes or "system/smtp" to receive message from all smtp // changes or "system" to receive changes for all paths beginning with // "system". A path is equal to a topic in a PubSub system. Path cannot be // empty means you cannot listen to all changes. Returns a unique identifier // for the Subscriber for later removal, or an error. Subscribe(fqPath string, mr MessageReceiver) (subscriptionID int, err error) }
Subscriber represents the overall service to receive subscriptions from MessageReceiver interfaces. This interface is at the moment only implemented by the config.Service.
type Value ¶
type Value struct { // Path optionally assigned to, to know to which path a value belongs to and to // provide different converter behaviour. Path Path // CSVColumnSep defines the CSV column separator, default a comma. CSVReader *csv.Reader CSVComma rune // contains filtered or unexported fields }
Value represents an immutable value returned from the configuration service. A value is meant to be only for reading and not safe for concurrent use.
Example ¶
ExampleValue shows how to use the Value type to convert the raw byte slice value to the appropriate final type.
package main import ( "fmt" "github.com/corestoreio/pkg/config" "github.com/corestoreio/pkg/config/storage" "github.com/corestoreio/pkg/store/scope" ) func panicIfErr(errs ...error) { for _, err := range errs { if err != nil { panic(fmt.Sprintf("%+v", err)) } } } func main() { // Default storage engine with build-in in-memory map. // the NewService gets only instantiated once during app start up. configSrv := config.MustNewService(storage.NewMap(), config.Options{}) const ( routeCountries = "carriers/freeshipping/specificcountry" routeListingCount = "catalog/frontend/list_per_page_values" routeCookieLifetime = "web/cookie/cookie_lifetime" ) routesVals := []struct { route string data string }{ {routeCountries, `CH,LI,DE`}, {routeListingCount, `5,10,15,20,25`}, {routeCookieLifetime, `7200s`}, } p := new(config.Path) for _, pv := range routesVals { panicIfErr( p.Parse(pv.route), configSrv.Set(p, []byte(pv.data)), ) } // This instance of makeScoped gets created somewhere deep in the program. // The numbers 1 and 2 are chosen here randomly. scpd := configSrv.Scoped(1, 2) cntryVal := scpd.Get(scope.Default, routeCountries) countries, err := cntryVal.Strs() panicIfErr(err) fmt.Printf("%s: %#v\n", routeCountries, countries) fmt.Printf("%s: %q\n", routeCountries, cntryVal.UnsafeStr()) listingCount, err := scpd.Get(scope.Default, routeListingCount).Ints() panicIfErr(err) fmt.Printf("%s: %#v\n", routeListingCount, listingCount) keksLifetime, ok, err := scpd.Get(scope.Default, routeCookieLifetime).Duration() panicIfErr(err) fmt.Printf("%s: found: %t %#v\n", routeCookieLifetime, ok, keksLifetime) }
Output: carriers/freeshipping/specificcountry: []string{"CH", "LI", "DE"} carriers/freeshipping/specificcountry: "CH,LI,DE" catalog/frontend/list_per_page_values: []int{5, 10, 15, 20, 25} web/cookie/cookie_lifetime: found: true 7200000000000
func (*Value) ConstantTimeCompare ¶
ConstantTimeCompare compares in a constant time manner data with the underlying value retrieved from the config service. Useful for passwords and other hashes.
func (*Value) Duration ¶
Duration converts the underlying converted data into the final type. Uses internally time.ParseDuration
func (*Value) Equal ¶
Equal compares if current object is fully equal to v2 object. Path and data must be equal. Nil safe.
func (*Value) EqualData ¶
EqualData compares if the data part of the current value is equal to v2. Nil safe. Does not use constant time for byte comparison, not secure for passwords.
func (*Value) Float64s ¶
Float64s splits the converted data using the CSVComma and appends it to `ret`.
func (*Value) Int64s ¶
Int64s converts the underlying byte slice into an int64 slice using v.CSVComma as a separator. The result gets append to argument `ret`.
func (*Value) Ints ¶
Ints converts the underlying byte slice into an int64 slice using v.CSVComma as a separator. The result gets append to argument `ret`.
func (*Value) IsEqual ¶
IsEqual does a constant time comparison of the underlying data with the input data `d`. Useful for passwords. Only equal when no error occurs.
func (*Value) IsValid ¶
IsValid returns the last error or in case when a Path is really not valid, returns an error with kind NotValid.
func (*Value) Str ¶
Str returns the underlying value as a string. Ok is true when data slice bytes are not nil. Whereas function String implements fmt.Stringer and returns something different.
func (*Value) String ¶
String implements fmt.Stringer and returns the textual representation and Go syntax escaped of the underlying data. It might print the error in the string.
func (*Value) Time ¶
Time parses a MySQL/MariaDB like time format: "2006-01-02 15:04:05.999999999 07:00" up to 35 places supports. Minimal format must be a year, e.g. 2006. time.UTC location gets used.
func (*Value) Uint64s ¶
Uint64s converts the underlying byte slice into an int64 slice using v.CSVComma as a separator. The result gets append to argument `ret`.
func (*Value) UnmarshalBinaryTo ¶
func (v *Value) UnmarshalBinaryTo(tu encoding.BinaryUnmarshaler) error
UnmarshalBinaryTo wrapper to use encoding.BinaryUnmarshaler for decoding the binary bytes. Useful for custom types.
func (*Value) UnmarshalTextTo ¶
func (v *Value) UnmarshalTextTo(tu encoding.TextUnmarshaler) error
UnmarshalTextTo wrapper to use encoding.TextUnmarshaler for decoding the textual bytes. Useful for custom types.
func (*Value) UnmarshalTo ¶
UnmarshalTo decodes the value into the final type. vPtr must be a pointer. The function signature for `fn` matches e.g. json.Unmarshal, xml.Unmarshal and many others.
func (*Value) UnsafeBool ¶
UnsafeBool same as Bool but ignores errors.
func (*Value) UnsafeDuration ¶
UnsafeDuration same as Duration but ignores all errors.
func (*Value) UnsafeFloat64 ¶
UnsafeFloat64 same as Float64 but ignores errors.
func (*Value) UnsafeInt64 ¶
UnsafeInt64 same as Int64 but ignores all errors
func (*Value) UnsafeTime ¶
UnsafeTime same as Time but ignores all errors.
func (*Value) UnsafeUint64 ¶
UnsafeUint64 same as Uint64 but ignores all errors.
func (*Value) WriteTo ¶
WriteTo writes the converted raw data to w. WriterTo is the interface that wraps the WriteTo method.
WriteTo writes data to w until there's no more data to write or when an error occurs. The return value n is the number of bytes written. Any error encountered during the write is also returned.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package deprecated source provides a slice type for handling config sources to be used in config/models.
|
Package deprecated source provides a slice type for handling config sources to be used in config/models. |
Package observer provides validators and modifiers for configuration values.
|
Package observer provides validators and modifiers for configuration values. |
Package storage provides the available storage engines for level 1 and level 2 caches.
|
Package storage provides the available storage engines for level 1 and level 2 caches. |