Skip to content

Commit

Permalink
add ability to load config with default values
Browse files Browse the repository at this point in the history
  • Loading branch information
aranw committed Nov 6, 2024
1 parent e6e0613 commit 75f52d0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 22 deletions.
48 changes: 27 additions & 21 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,31 @@ func ParseFS[T any](fs embed.FS, path string) (*T, error) {
b, err := fs.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading config from embed.FS: %w", err)
} else if err := UnmarshalConfig(&cfg, b); err != nil {
return nil, fmt.Errorf("unmarshalling config: %w", err)
}
if cfg, ok := interface{}(cfg).(interface {
Validate() error
}); ok {
if err := cfg.Validate(); err != nil {
return nil, fmt.Errorf("validating config: %w", err)
}
}

return cfg, nil
return parse(cfg, b)
}

// Parse takes the given path and attempts to read and unmarshal the config
// The given config will also be validated if it has a Validate function on it
func Parse[T any](path string) (*T, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading config file: %w", err)
}
var cfg *T
return parse(cfg, b)
}

// ParseWithConfig takes the given config and path and attempts to read and unmarshal the config
// The given config can be populated with default values
// If the given config implements a `Validate() error` function this will be called
func ParseWithConfig[T any](cfg *T, path string) (*T, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading config file: %w", err)
} else if err := UnmarshalConfig(&cfg, b); err != nil {
return nil, fmt.Errorf("unmarshalling config: %w", err)
}
if cfg, ok := interface{}(cfg).(interface {
Validate() error
}); ok {
if err := cfg.Validate(); err != nil {
return nil, fmt.Errorf("validating config: %w", err)
}
}

return cfg, nil
return parse(cfg, b)
}

// UnmarshalConfig takes the provided yaml data and unmarshals it
Expand All @@ -64,3 +55,18 @@ func UnmarshalConfig[T any](cfg *T, data []byte) error {
dec.KnownFields(true)
return dec.Decode(&cfg)
}

func parse[T any](cfg *T, b []byte) (*T, error) {
if err := UnmarshalConfig(&cfg, b); err != nil {
return nil, fmt.Errorf("unmarshalling config: %w", err)
}
if cfg, ok := interface{}(cfg).(interface {
Validate() error
}); ok {
if err := cfg.Validate(); err != nil {
return nil, fmt.Errorf("validating config: %w", err)
}
}

return cfg, nil
}
20 changes: 19 additions & 1 deletion config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import (
)

type TestStruct struct {
SomeValue string `yaml:"some_value"`
SomeValue string `yaml:"some_value"`
SecondValue string `yaml:"second_value"`
}

func (t *TestStruct) Validate() error {
Expand Down Expand Up @@ -60,6 +61,23 @@ func TestParseFS(t *testing.T) {
})
}

func TestParseWithConfig(t *testing.T) {
t.Run("successfully load and unmarshals config with defaults", func(t *testing.T) {
cfg := &TestStruct{
SecondValue: "This is the default",
}

cfg, err := ParseWithConfig[TestStruct](cfg, "testdata/test1.yaml")
if err != nil {
t.Fatal(err)
}

qt.Assert(t, qt.Equals(cfg.SomeValue, "this is for testing purposes"))
qt.Assert(t, qt.Equals(cfg.SecondValue, "This is the default"))
})

}

func TestParse(t *testing.T) {

t.Run("successfully load and unmarshals config", func(t *testing.T) {
Expand Down

0 comments on commit 75f52d0

Please sign in to comment.