Help us shape the future of Go! Take the 2026 Go Developer Survey

fig

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jan 16, 2020 License: Apache-2.0 Imports: 12 Imported by: 78

README

fig

Build Status Go Report Card Coverage Status License GoDoc

fig

fig loads configuration files into Go structs with extra juice for validating fields and setting defaults.

Why fig?

Define your config, validations and defaults all within a single struct. Fig does the rest!

Additionally, fig:

  • Understands time.Time & time.Duration
  • Has only 3 external dependencies
  • Exposes a tiny API
  • Decodes .yaml, .json and .toml files
  • Is extensively tested

Getting Started

$ go get -d github.com/kkyr/fig

Define your configuration file:

# config.yaml

build: "2020-01-09T12:30:00Z"

server:
    ports:
      - 8080
cleanup: 1h

logger:
    level: "warn"
    trace: true

Define your struct and load it using fig:

package main

import (
  "fmt"

  "github.com/kkyr/fig"
)

type Config struct {
  Build  time.Time `fig:"build,required"`
  Server struct {
    Host    string        `fig:"host,default=127.0.0.1"`
    Ports   []int         `fig:"ports,default=[80,443]"`
    Cleanup time.Duration `fig:"cleanup,default=30m"`
  }
  Logger struct {
    Level string `fig:"level,default=info"`
    Trace bool   `fig:"trace"`
  }
}

func main() {
  var cfg Config
  err := fig.Load(&cfg)
  // handle your err
  
  fmt.Printf("%+v\n", cfg)
  // Output: {Build:2019-12-25 00:00:00 +0000 UTC Server:{Host:127.0.0.1 Ports:[8080] Cleanup:1h0m0s} Logger:{Level:warn Trace:true}}
}

Fig searches by default for a file named config.yaml in the directory it is run from.

Change the behaviour based on your needs by passing additional parameters to Load():

fig.Load(&cfg,
  fig.File("settings.json"),
  fig.Dirs(".", "/etc/myapp", "/home/user/myapp"),
) // searches for ./settings.json, /etc/myapp/settings.json, /home/user/myapp/settings.json

Usage

See [godoc] for detailed usage documentation.

Contributing

PRs are welcome! Please ensure you add relevant tests & documentation prior to making one.

Documentation

Overview

Package fig provides a mechanism for loading configuration files into structs.

Config files may be defined in in yaml, json or toml format.

Example

Define your configuration file in the root of your project:

# config.yaml

build: "2020-01-09T12:30:00Z"

server:
  ports:
    - 8080
  cleanup: 1h

logger:
  level: "warn"
  trace: true

Define your struct and load it:

package main

import (
  "fmt"

  "github.com/kkyr/fig"
)

 type Config struct {
   Build  time.Time `fig:"build,required"`
   Server struct {
     Host    string        `fig:"host,default=127.0.0.1"`
     Ports   []int         `fig:"ports,default=[80,443]"`
     Cleanup time.Duration `fig:"cleanup,default=30m"`
   }
   Logger struct {
     Level string `fig:"level,default=info"`
     Trace bool   `fig:"trace"`
   }
 }

func main() {
  var cfg Config
  _ = fig.Load(&cfg)

  fmt.Printf("%+v\n", cfg)
  // Output: {Build:2019-12-25 00:00:00 +0000 UTC Server:{Host:127.0.0.1 Ports:[8080] Cleanup:1h0m0s} Logger:{Level:warn Trace:true}}
}

By default fig searches for a file named `config.yaml` in the directory it is run from. It can be configured to look elsewhere.

Configuration

Pass options as additional parameters to `Load()` to configure fig's behaviour.

File

Change the file and directories fig searches in with `File()`.

fig.Load(&cfg,
  fig.File("settings.json"),
  fig.Dirs(".", "home/user/myapp", "/opt/myapp"),
)

Fig searches for the file in dirs sequentially and uses the first matching file.

The decoder (yaml/json/toml) used is picked based on the file's extension.

Tag

The name of the struct tag that fig uses can be changed with `Tag()`.

type Config struct {
  Host  string `config:"host,required"`
  Level string `config:"level,default=info"`
}

var cfg Config
fig.Load(&cfg, fig.Tag("config"))

By default fig uses the tag name `fig`.

Time

Change the layout fig uses to parse times using `TimeLayout()`.

type Config struct {
  Date time.Time `fig:"date,default=12-25-2019"`
}

var cfg Config
fig.Load(&cfg, fig.TimeLayout("01-02-2006"))

fmt.Printf("%+v", cfg)
// Output: {Date:2019-12-25 00:00:00 +0000 UTC}

By default fig parses time using the `RFC.3339` layout (`2006-01-02T15:04:05Z07:00`).

Validation

Fields can be validated by adding an appropriate key to the field tag. A maximum of one validation may be added to each field.

Required

A required key in the field tag causes fig to check if the field has been set after it's loaded from the config file. Required fields that are not set are returned as an error.

type Config struct {
  Host string `fig:"host,required"` // or `fig:",required"
}

Fig uses the following properties to check if a field is set:

basic types:           != to its zero value ("" for str, 0 for int, etc.)
slices, arrays:        len() > 0
pointers*, interfaces: != nil
structs:               always true (use a struct pointer to check for struct presence)
time.Time:             !time.IsZero()
time.Duration:         != 0

*non-nil pointers to non-struct types (except time.Time) are de-referenced and then checked

See example below to help understand:

type Config struct {
  A string    `fig:",required"`
  B *string   `fig:",required"`
  C int       `fig:",required"`
  D *int      `fig:",required"`
  E []float32 `fig:",required"`
  F struct{}  `fig:",required"`
  G *struct{} `fig:",required"`
  H struct {
    I interface{} `fig:",required"`
    J interface{} `fig:",required"`
  } `fig:",required"`
  K *[]bool    `fig:",required"`
  L []uint     `fig:",required"`
  M *time.Time `fig:",required"`
}

var cfg Config

// simulate loading of config file
b := ""
cfg.B = &b
cfg.H.I = 5.5
cfg.K = &[]bool{}
cfg.L = []uint{5}
m := time.Time{}
cfg.M = &m

err := fig.Load(&cfg)
fmt.Print(err)
// A: required, B: required, C: required, D: required, E: required, G: required, H.J: required, K: required, M: required

Default

A default key in the field tag causes fig to fill the field with the value specified only if the field is not set. It must be in the format default=value.

Fig attempts to parse the value based on the field's type. If parsing fails then an error is returned.

type Config struct {
  Port int `fig:"port,default=8000"` // or `fig:",default=8000"
}

A default value can be set for the following types:

all basic types*
time.Time
time.Duration
slices (of above types)

*complex not supported

Slice defaults must be enclosed in square brackets and successive values separated by a comma:

type Config struct {
  Durations []time.Duration `fig:",default=[30m,1h,90m,2h]"
}

Copyright 2020 Kyriacos Kyriacou <contact@kkyr.io>

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Copyright 2020 Kyriacos Kyriacou <contact@kkyr.io>

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Index

Constants

View Source
const (
	// DefaultFilename is the default filename of the config file that fig looks for.
	DefaultFilename = "config.yaml"
	// DefaultDir is the default directory that fig searches in for the config file.
	DefaultDir = "."
	// DefaultTag is the default struct tag name that fig uses for field metadata.
	DefaultTag = "fig"
	// DefaultTimeLayout is the default time layout that fig uses to parse times.
	DefaultTimeLayout = time.RFC3339
)

Variables

This section is empty.

Functions

func Load

func Load(cfg interface{}, options ...Option) error

Load reads a configuration file and loads it into the given struct. The parameter `cfg` must be a pointer to a struct.

By default fig looks for a file `config.yaml` in the current directory and uses the struct field tag `fig` for matching field names and validation. To alter this behaviour pass additional parameters as options.

A field can be marked as required by adding a `required` key in the field's struct tag. If a required field is not set by the configuration file an error is returned.

type config struct {
  Env string `fig:"env,required"` // or `fig:",required"`
}

A field can be configured with a default value by adding a `default=value` in the field's struct tag. If a field is not set by the configuration file then the default value is set.

type config struct {
  Level string `fig:"level,default=info"` // or `fig:",default=info"`
}

A single field may not be marked as both `required` and `default`.

Types

type Option

type Option func(f *fig)

Option configures how fig loads the configuration.

func Dirs

func Dirs(dirs ...string) Option

Dirs returns an option that configures the directories that fig searches to find the configuration file.

Directories are searched sequentially and the first one with a matching config file is used.

This is useful when you don't know where exactly your configuration will be during run-time:

fig.Load(&cfg, fig.Dirs(".", "/etc/myapp", "/home/user/myapp"))

If this option is not used then fig looks in the directory it is run from.

func File

func File(name string) Option

File returns an option that configures the filename that fig looks for to provide the config values.

The name must include the extension of the file. Supported file types are `yaml`, `yml`, `json` and `toml`.

fig.Load(&cfg, fig.File("config.toml"))

If this option is not used then fig looks for a file with name `config.yaml`.

func Tag

func Tag(tag string) Option

Tag returns an option that configures the tag that fig uses when searching for struct tags in fields.

fig.Load(&cfg, fig.Tag("config"))

If this option is not used then fig uses the tag `fig`.

func TimeLayout

func TimeLayout(layout string) Option

TimeLayout returns an option that conmfigures the time layout that fig uses when parsing a time in a config file or in the default tag for time.Time fields.

fig.Load(&cfg, fig.TimeLayout("2006-01-02"))

If this option is not used then fig parses times using `time.RFC3339` layout.

Jump to

Keyboard shortcuts

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