A minimalist Go configuration library

fig

godoc build status semver tag go report card coverage status license

fig

fig is a tiny library for loading an application's config file and its environment into a Go struct. Individual fields can have default values defined or be marked as required.

Why fig?

  • Define your configuration, validations and defaults in a single location
  • Optionally load from the environment as well
  • Only 3 external dependencies
  • Full support fortime.Time & time.Duration
  • Tiny API
  • Decoders for .yaml, .json and .toml files

Getting Started

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

Define your config file:

# config.yaml

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

server:
    ports:
      - 8080
    cleanup: 1h

logger:
    level: "warn"
    trace: true

Define your struct along with validations or defaults:

package main

import (
  "fmt"

  "github.com/kkyr/fig"
)

type Config struct {
  Build  time.Time `fig:"build" validate:"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}}
}

If a field is not set and is marked as required then an error is returned. If a default value is defined instead then that value is used to populate the field.

Fig searches for a file named config.yaml in the directory it is run from. Change the lookup behaviour 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

Environment

Need to additionally fill fields from the environment? It's as simple as:

fig.Load(&cfg, fig.UseEnv("MYAPP"))

Usage

See usage examples.

Documentation

See go.dev for detailed documentation.

Contributing

PRs are welcome! Please explain your motivation for the change in your PR and ensure your change is properly tested and documented.

Comments
  • Add regexp.Regexp support

    Add regexp.Regexp support

    It's useful to support validated regular expressions in configuration. Previously, we could represent these fields as raw pattern strings and compile them in application code. By supporting Regexp as a first-class field type, we get a smaller application code and more immediate error reporting without complicating the API.

  • Allow providing config values only via environment

    Allow providing config values only via environment

    The changes add a new NoFile option and the new fig.ignoreFile field.

    Giving this option to Load() will:

    • Disable the default file lookup process
    • The File and Dir option still work as before but become ineffective in the presence of NoFile option.

    Signed-off-by: Ravi Shekhar Jethani [email protected]

  • Value from environment

    Value from environment

    Thank you for the library. It is something I've been planning to write myself. But I'd still hope for one more feature. Especially for projects packaged as docker images. Could you support some sort of environment variable interpolation syntax? Like ${FOOBAR} being read from the environment variable FOOBAR?

  • Default bool items not being set correctly when not present in config

    Default bool items not being set correctly when not present in config

    Howdy,

    According to the documentation:

    A default key in the field tag makes fig fill the field with the value specified when the field is not otherwise set.

    Given the following config.yaml:

    itemone:
      enabled: false
    

    With the following program:

    package main
    
    import (
        "fmt"
        "github.com/kkyr/fig"
    )
    
    type Config struct {
        ItemOne  ItemOne   `default:{}`
        ItemTwo  ItemTwo   `default:{}`
    
    }
    
    type ItemOne struct {
        Enabled     bool    `fig:"enabled" default:true`
    }
    
    type ItemTwo struct {
        Enabled     bool    `fig:"enabled" default:true`
    }
    
    func main() {
        var conf Config
        err := fig.Load(&conf)
        if err != nil {
            panic(err)
        }
    
        fmt.Printf("Config %+v", conf)
    }
    

    What was expected: Field ItemTwo.Enabled would be set to boolean true.

    What actually happened: Field ItemTwo.Enabled is set to boolean false:

    Config {ItemOne:{Enabled:false} ItemTwo:{Enabled:false}}
    

    I've slimmed down an existing program to this most basic PoC to rule out other code in my application being a problem, though my usage is perhaps still incorrect.

  • Add an option to explicitly set which config file to use

    Add an option to explicitly set which config file to use

    It would be nice to have an option/function to explicitly load the config file that was provided by user. The idea is to have smth like:

    package main
    
    var configFile = flag.String("config", "app.yaml", "Config file to use") // so it may have the value like `/usr/local/etc/name_by_user.yaml`
    
    func main() {
        flag.Parse()
        err := fig.Load(&cfg, fig.File(*configFile))
    }
    

    In the current implementation it wouldn't work because fig will search for the file in the current directory (.) only by default. But it also can check for the file existence using only given path:

    func (f *fig) findCfgFile() (path string, err error) {
    	for _, dir := range f.dirs {
    		path = filepath.Join(dir, f.filename)
    		if fileExists(path) {
    			return
    		}
    	}
            if path = f.filename; fileExists(path) {
                return
            }
    	return "", fmt.Errorf("%s: %w", f.filename, ErrFileNotFound)
    }
    
  • Feature request: Updating configuration files

    Feature request: Updating configuration files

    It would be nice to have an API to create/update a configuration file, keeping constraints in mind.

    The call would be something like:

    // do something with the settings' attributes
    // ....
    // Update the configuration file and check the constraints
    fig.Update(&cfg, fig.File("settings.json"), fig.Dir("/app/conf"))
    
  • Fields of type time.Duration should fail when the input is an integer

    Fields of type time.Duration should fail when the input is an integer

    The duration parser provided by the standard library fails when it's input doesn't include a time unit. As expected, fig also fails in such a case, but it doesn't when the input is not wrapped in quotes because it's interpreted as an integer and not a string.

    For example, given:

    // config.yaml
    timeout: 1
    
    // main.go
    package main
    
    import (
    	"fmt"
    	"log"
    	"time"
    
    	"github.com/kkyr/fig"
    )
    
    type Config struct {
    	Timeout time.Duration `fig:"timeout" validate:"required"`
    }
    
    func main() {
    	var cfg Config
    	if err := fig.Load(&cfg); err != nil {
    		log.Fatal(err)
    	}
    
    	fmt.Printf("%+v\n", cfg)
    }
    

    I would expect it to fail because timeout: 1 doesn't have a time unit, instead the config is parsed without errors and the set value is 1ns.

    Maybe this could be fixed by adding a check of Int (and maybe float?) values in StringToTimeDurationHookFunc, although I may be missing some other cases.

  • Allow for multiple possible file names

    Allow for multiple possible file names

    Hi,

    I would like it, if it would be possible to search for different file names (same as dirs). ex allow ./config.json ./config.yaml and ./config.toml

    Thanks for the nice work.

  • fig should be more customizable via hooks

    fig should be more customizable via hooks

    fig uses the very powerful mapstructure under the hood just like viper. But unlike viper or uconfig it does not expose some sort of hook/middleware mechanism so that user defined logic can be executed as part of loading config

    Introducing such a behavior might break backwards compatibility but it would be worth it in the long run.

  • Make it possible to use only environment variables (with no config file)

    Make it possible to use only environment variables (with no config file)

    Currently, environment variables can't be used as a full replacement for a config file, only in addition to one. If no config file exists, I think it should just use the defaults from the struct, check environment variables if UseEnv is set, and then return an error if required stuff is not set (e.g. port: required validation failed (using only environment as no config file could be found)).

go-up! A simple configuration library with recursive placeholders resolution and no magic.

go-up! A simple configuration library with placeholders resolution and no magic. go-up provides a simple way to configure an application from multiple

Nov 23, 2022
go implementation of lightbend's HOCON configuration library https://github.com/lightbend/config

HOCON (Human-Optimized Config Object Notation) Configuration library for working with the Lightbend's HOCON format. HOCON is a human-friendly JSON sup

Dec 3, 2022
🛠 A configuration library for Go that parses environment variables, JSON files, and reloads automatically on SIGHUP
🛠 A configuration library for Go that parses environment variables, JSON files, and reloads automatically on SIGHUP

config A small configuration library for Go that parses environment variables, JSON files, and reloads automatically on SIGHUP. Example func main() {

Dec 11, 2022
Golang library for managing configuration data from environment variables

envconfig import "github.com/kelseyhightower/envconfig" Documentation See godoc Usage Set some environment variables: export MYAPP_DEBUG=false export

Dec 26, 2022
Light weight, extensible configuration management library for Go. Built in support for JSON, TOML, YAML, env, command line, file, S3 etc. Alternative to viper.
Light weight, extensible configuration management library for Go. Built in support for JSON, TOML, YAML, env, command line, file, S3 etc. Alternative to viper.

koanf (pronounced conf; a play on the Japanese Koan) is a library for reading configuration from different sources in different formats in Go applicat

Jan 8, 2023
A flexible and composable configuration library for Go that doesn't suck

croconf A flexible and composable configuration library for Go that doesn't suck Ned's spec for Go configuration which doesn't suck: Fully testable: t

Nov 17, 2022
A flexible and composable configuration library for Go that doesn't suck

croconf A flexible and composable configuration library for Go Why? We know that there are plenty of other Go configuration and CLI libraries out ther

Nov 17, 2022
Cfginterpolator is an interpolate library in golang allowing to include data from external sources in your configuration

cfginterpolator cfginterpolator is an interpolate library in golang allowing to include data from external sources in your configuration cfginterpolat

Dec 14, 2021
Golang library for reading properties from configuration files in JSON and YAML format or from environment variables.

go-config Golang library for reading properties from configuration files in JSON and YAML format or from environment variables. Usage Create config in

Aug 22, 2022
Tinyini - Bare-bones Go library for reading INI-like configuration files

tinyini tinyini is a minimalistic library for parsing INI-like configuration files. example configuration file globalkey = globalvalue [section] key

Jan 10, 2022
✨Clean and minimalistic environment configuration reader for Golang

Clean Env Minimalistic configuration reader Overview This is a simple configuration reading tool. It just does the following: reads and parses configu

Jan 8, 2023
12 factor configuration as a typesafe struct in as little as two function calls

Config Manage your application config as a typesafe struct in as little as two function calls. type MyConfig struct { DatabaseUrl string `config:"DAT

Dec 13, 2022
JSON or YAML configuration wrapper with convenient access methods.

Config Package config provides convenient access methods to configuration stored as JSON or YAML. This is a fork of the original version. This version

Dec 16, 2022
Configure is a Go package that gives you easy configuration of your project through redundancy

Configure Configure is a Go package that gives you easy configuration of your project through redundancy. It has an API inspired by negroni and the fl

Sep 26, 2022
An opinionated configuration loading framework for Containerized and Cloud-Native applications.
An opinionated configuration loading framework for Containerized and Cloud-Native applications.

Opinionated configuration loading framework for Containerized and 12-Factor compliant applications. Read configurations from Environment Variables, an

Dec 16, 2022
Load configuration in cascade from multiple backends into a struct
Load configuration in cascade from multiple backends into a struct

Confita is a library that loads configuration from multiple backends and stores it in a struct. Supported backends Environment variables JSON files Ya

Jan 1, 2023
goconfig uses a struct as input and populates the fields of this struct with parameters from command line, environment variables and configuration file.

goconfig goconfig uses a struct as input and populates the fields of this struct with parameters from command line, environment variables and configur

Dec 15, 2022
Go configuration made easy!

gofigure Go configuration made easy! Just define a struct and call Gofigure Supports strings, ints/uints/floats, slices and nested structs Supports en

Sep 26, 2022
Harvest configuration, watch and notify subscriber

Harvester Harvester is a configuration library which helps setting up and monitoring configuration values in order to dynamically reconfigure your app

Dec 26, 2022