Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Config interface into a struct #12

Merged
merged 3 commits into from
Jan 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
### Changed

- Split `Load` method in the `Config` interface into `Load` and `PostLoad` methods. [#7](https://github.com/go-nacelle/config/pull/7)
- The `Config` interface is now a struct with the same name and set of methods. [#12](https://github.com/go-nacelle/config/pull/12)

## [v1.2.1] - 2020-09-30

Expand Down
82 changes: 33 additions & 49 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,6 @@ import (
"strings"
)

// Config is a structure that can populate the exported fields of a
// struct based on the value of the field `env` tags.
type Config interface {
// Init prepares state required by the registered sourcer. This
// method should be called before calling any other method.
Init() error

// Load populates a configuration object. The given tag modifiers
// are applied to the configuration object pre-load.
Load(interface{}, ...TagModifier) error

// Call the PostLoad method of the given target if it conforms to
// the PostLoadConfig interface.
PostLoad(interface{}) error

// Assets returns a list of names of assets that compose the
// underlying sourcer. This can be a list of matched files that are
// read, or a token that denotes a fixed source.
Assets() []string

// Dump returns the full content of the underlying sourcer. This
// is used by the logging package to show the content of the
// environment and config files when a value is missing or otherwise
// illegal.
Dump() map[string]string

// Describe returns a description of the struct relevant to the given
// config object. Field descriptions include the field name, the values
// of struct tags matching the configured sourcer, whether or not the
// field must be populated, and a default value (if any).
Describe(interface{}, ...TagModifier) (*StructDescription, error)
}

type StructDescription struct {
Fields []FieldDescription
}
Expand All @@ -59,30 +26,34 @@ type PostLoadConfig interface {
PostLoad() error
}

type config struct {
// Config is a structure that can populate the exported fields of a
// struct based on the value of the field `env` tags.
type Config struct {
sourcer Sourcer
logger Logger
maskedKeys []string
}

var _ Config = &config{}

// NewConfig creates a config loader with the given sourcer.
func NewConfig(sourcer Sourcer, configs ...ConfigOptionsFunc) Config {
func NewConfig(sourcer Sourcer, configs ...ConfigOptionsFunc) *Config {
options := getConfigOptions(configs)

return &config{
return &Config{
sourcer: sourcer,
logger: options.logger,
maskedKeys: options.maskedKeys,
}
}

func (c *config) Init() error {
// Init prepares state required by the registered sourcer. This
// method should be called before calling any other method.
func (c *Config) Init() error {
return c.sourcer.Init()
}

func (c *config) Load(target interface{}, modifiers ...TagModifier) error {
// Load populates a configuration object. The given tag modifiers
// are applied to the configuration object pre-load.
func (c *Config) Load(target interface{}, modifiers ...TagModifier) error {
config, err := ApplyTagModifiers(target, modifiers...)
if err != nil {
return err
Expand Down Expand Up @@ -112,23 +83,36 @@ func (c *config) Load(target interface{}, modifiers ...TagModifier) error {
return nil
}

func (c *config) PostLoad(target interface{}) error {
// Call the PostLoad method of the given target if it conforms to
// the PostLoadConfig interface.
func (c *Config) PostLoad(target interface{}) error {
if plc, ok := target.(PostLoadConfig); ok {
return plc.PostLoad()
}

return nil
}

func (c *config) Assets() []string {
// Assets returns a list of names of assets that compose the
// underlying sourcer. This can be a list of matched files that are
// read, or a token that denotes a fixed source.
func (c *Config) Assets() []string {
return c.sourcer.Assets()
}

func (c *config) Dump() map[string]string {
// Dump returns the full content of the underlying sourcer. This
// is used by the logging package to show the content of the
// environment and config files when a value is missing or otherwise
// illegal.
func (c *Config) Dump() map[string]string {
return c.sourcer.Dump()
}

func (c *config) Describe(target interface{}, modifiers ...TagModifier) (*StructDescription, error) {
// Describe returns a description of the struct relevant to the given
// config object. Field descriptions include the field name, the values
// of struct tags matching the configured sourcer, whether or not the
// field must be populated, and a default value (if any).
func (c *Config) Describe(target interface{}, modifiers ...TagModifier) (*StructDescription, error) {
config, err := ApplyTagModifiers(target, modifiers...)
if err != nil {
return nil, err
Expand All @@ -137,7 +121,7 @@ func (c *config) Describe(target interface{}, modifiers ...TagModifier) (*Struct
return c.describe(config)
}

func (c *config) load(target interface{}) []error {
func (c *Config) load(target interface{}) []error {
objValue, objType, err := getIndirect(target)
if err != nil {
return []error{err}
Expand All @@ -146,7 +130,7 @@ func (c *config) load(target interface{}) []error {
return c.loadStruct(objValue, objType)
}

func (c *config) loadStruct(objValue reflect.Value, objType reflect.Type) []error {
func (c *Config) loadStruct(objValue reflect.Value, objType reflect.Type) []error {
if objType.Kind() != reflect.Struct {
return []error{fmt.Errorf(
"invalid embedded type in configuration struct",
Expand Down Expand Up @@ -186,7 +170,7 @@ func (c *config) loadStruct(objValue reflect.Value, objType reflect.Type) []erro
return errors
}

func (c *config) loadEnvField(
func (c *Config) loadEnvField(
fieldValue reflect.Value,
name string,
tagValues []string,
Expand Down Expand Up @@ -240,7 +224,7 @@ func (c *config) loadEnvField(
return nil
}

func (c *config) describe(target interface{}) (*StructDescription, error) {
func (c *Config) describe(target interface{}) (*StructDescription, error) {
objValue, objType, err := getIndirect(target)
if err != nil {
return nil, err
Expand All @@ -249,7 +233,7 @@ func (c *config) describe(target interface{}) (*StructDescription, error) {
return c.describeStruct(objValue, objType)
}

func (c *config) describeStruct(objValue reflect.Value, objType reflect.Type) (*StructDescription, error) {
func (c *Config) describeStruct(objValue reflect.Value, objType reflect.Type) (*StructDescription, error) {
if objType.Kind() != reflect.Struct {
return nil, fmt.Errorf("invalid embedded type in configuration struct")
}
Expand Down
1 change: 0 additions & 1 deletion gen.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package config

//go:generate go-mockgen -f github.com/go-nacelle/config -i Config -o mock_config_test.go
//go:generate go-mockgen -f github.com/go-nacelle/config -i Logger -o mock_logger_test.go
//go:generate go-mockgen -f github.com/go-nacelle/config -i Sourcer -o mock_sourcer_test.go
//go:generate go-mockgen -f github.com/go-nacelle/config -i FileSystem -o mock_fs_test.go
4 changes: 2 additions & 2 deletions logging_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type nilLogger struct{}

func (nilLogger) Printf(format string, args ...interface{}) {}

func (c *config) dumpSource() error {
func (c *Config) dumpSource() error {
chunk := map[string]interface{}{}
for key, value := range c.Dump() {
if c.isMasked(key) {
Expand All @@ -34,7 +34,7 @@ func (c *config) dumpSource() error {
return nil
}

func (c *config) isMasked(target string) bool {
func (c *Config) isMasked(target string) bool {
for _, key := range c.maskedKeys {
if strings.ToLower(key) == strings.ToLower(target) {
return true
Expand Down
Loading