Lightweight, zero-dependency, and extendable configuration management library for Go

uConfig GoDoc Build Status Go Report Card Coverage

Lightweight, zero-dependency, and extendable configuration management.

uConfig is extremely light and extendable configuration management library with zero dependencies. Every aspect of configuration is provided through a plugin, which means you can have any combination of flags, environment variables, defaults, secret providers, Kubernetes Downward API, and what you want, and only what you want, through plugins.

uConfig takes the config schema as a struct decorated with tags, nesting is supported.

Supports all basic types, time.Duration, and any other type through encoding.TextUnmarshaler interface. See the flat view package for details.

Example Configuration:

package database
// Config holds the database configurations.
type Config struct {
  Address  string `default:"localhost"`
  Port     string `default:"28015"`
  Database string `default:"my-project"`
}
package redis
// Config describes the requirement for redis client.
type Config struct {
  Address  string        `default:"redis-master"`
  Port     string        `default:"6379"`
  Password string        `secret:""`
  DB       int           `default:"0"`
  Expire   time.Duration `default:"5s"`
}
package main



import (
  "encoding/json"

  "github.com/omeid/uconfig"

  "$PROJECT/redis"
  "$PROJECT/database"
)

// Config is our application config.
type Config struct {

  // yes you can have slices.
  Hosts    []string `default:"localhost,localhost.local" usage:"the ip or domains to bind to"`

  Redis    redis.Config
  Database database.Config

}



func main() {

  conf := &Config{}

  confFiles := uconfig.Files{
    {"config.json", json.Unmarshal}
    // you can add more files if you like,
    // they will be applied in the given order.
  }

  c, err := uconfig.Classic(&conf, confFiles)
  if err != nil {
    c.Usage()
    os.Exit(1)
  }

  // use conf as you please.
  fmt.Printf("start with hosts set to: %#v\n", conf.Hosts)

}

Run this program with a bad flag or value would print out the usage like so:

flag provided but not defined: -x

Supported Fields:
FIELD                FLAG                  ENV                  DEFAULT                      USAGE
-----                -----                 -----                -------                      -----
Hosts                -hosts                HOSTS                localhost,localhost.local    the ip or domains to bind to
Redis.Address        -redis-address        REDIS_ADDRESS        redis-master
Redis.Port           -redis-port           REDIS_PORT           6379
Redis.Password       -redis-password       REDIS_PASSWORD
Redis.DB             -redis-db             REDIS_DB             0
Redis.Expire         -redis-expire         REDIS_EXPIRE         5s
Database.Address     -database-address     DATABASE_ADDRESS     localhost
Database.Port        -database-port        DATABASE_PORT        28015
Database.Database    -database-database    DATABASE_DATABASE    my-project

Custom names:

Sometimes you might want to use a different env var, or flag name for backwards compatibility or other reasons, you have two options.

  1. uconfig tag

You can change the name of a field as seen by unconfig. This option supports the usual nesting prefixing. See the port example below.

  1. Plugin specific tags

Most plugins support controlling the field name as seen by that specific plugin.

This option does not support nesting prefixes. See the Database field in the example below.

package database

// Config holds the database configurations.
type Database struct {
  Address  string `default:"localhost"`
  Port     string `default:"28015" uconfig:"Service.Port"`
  Database string `default:"my-project" env:"DB_NAME" flag:"main-db-name"`
}
package main

// Config is our application config.
type Config struct {

  // yes you can have slices.
  Hosts    []string `default:"localhost,localhost.local"`

  Redis    redis.Config
  Database database.Config
}

Which should give you the following settings:

Supported Fields:
FIELD                    FLAG                      ENV                      DEFAULT                      USAGE
-----                    -----                     -----                    -------                      -----
Hosts                    -hosts                    HOSTS                    localhost,localhost.local    the ip or domains to bind to
Redis.Port               -redis-port               REDIS_PORT               6379
Redis.Password           -redis-password           REDIS_PASSWORD
Redis.DB                 -redis-db                 REDIS_DB                 0
Redis.Expire             -redis-expire             REDIS_EXPIRE             5s
Database.Address         -database-address         DATABASE_ADDRESS         localhost
Database.Service.Port    -database-service-port    DATABASE_SERVICE_PORT    28015
Database.Database        -main-db-db               DB_NAME                  my-project
exit status 1

For file based plugins, you will need to use the appropriate tags as used by your encoder of choice. For example:

package users

// Config holds the database configurations.
type Config struct {
  Host string `json:"bind_addr"`
}

Secrets Plugin

GoDoc

The secret provider allows you to grab the value of a config from anywhere you want. You simply need to implement the func(name string) (value string) function and pass it to the secrets plugin.

Unlike most other plugins, secret requires explicit secret:"" tag, this is because only specific config values like passwords and api keys come from a secret provider, compared to the rest of the config which can be set in various ways.

import (

  "github.com/omeid/uconfig"
  "github.com/omeid/uconfig/plugins/secret"
)
// Creds is an example of a config struct that uses secret values.
type Creds struct {
  // by default, secret plugin will generate a name that is identical
  // to env plugin, SCREAM_SNAKE_CASE, so in this case it will be
  // APIKEY however, following the standard uConfig nesting rules
  // in Config struct below, it becomes CREDS_APIKEY.
  APIKey   string `secret:""`
  // or you can provide your own name, which will not be impacted
  // by nesting or the field name.
  APIToken string `secret:"API_TOKEN"`
}

type Config struct {
  Redis   Redis
  Creds   Creds
}


func main() {

  conf := &Config{}


  files := uconfig.Files{
    {"config.json", json.Unmarshal}
  }

   // secret.New accepts a function that maps a secret name to it's value.
   secretPlugin := secret.New(func(name string) (string, error) {
      // you're free to grab the secret based on the name from wherever
      // you please, aws secrets-manager, hashicorp vault, or wherever.
      value, ok := secretSource.Get(name)

      if !ok {
        return "", ErrSecretNotFound
      }

      return value, nil
  })

  // then you can use the secretPlugin with uConfig like any other plugin.
  // Lucky, uconfig.Classic allows passing more plugins, which means
  // you can simply do the following for flags, envs, files, and secrets!
  _, err := uconfig.Classic(&value, files, secretPlugin)
  if err != nil {
    t.Fatal(err)
  }

}

Tests

For tests, you may consider the Must function to set the defaults, like so

package something

import (
  "testing"

  "github.com/omeid/uconfig"
  "github.com/omeid/uconfig/defaults"
)

func TestSomething(t *testing.T) error {

  conf := &YourConfigStruct{}

  // It will panic on error
  uconfig.Must(conf, defaults.New())

  // Use your conf as you please.
}

See the Classic source for how to compose plugins. For more details, see the godoc.

Extending uConfig:

uConfig provides a plugin mechanism for adding new sources of configuration. There are two kind of plugins, Walkers and Visitors.

To implement your own, see the examples.

Visitors

Visitors get a flat view of the configuration struct, which is a flat view of the structs regardless of nesting level, for more details see the flat package documentation.

Plugins that load the configurations from flat structures (e.g flags, environment variables, default tags) are good candidates for this type of plugin. See env plugin for an example.

Walkers

Walkers are used for configuration plugins that take the whole config struct and unmarshal the underlying content into the config struct. Plugins that load the configuration from files are good candidates for this.

See file plugin for an example.

Owner
O'meid
dead heroes can't tame the wicked.
O'meid
Comments
  • breaking: replace Field.Get() with Field.IsZeroValue()

    breaking: replace Field.Get() with Field.IsZeroValue()

    Hello, I was writing a required plugin and noticed Field.Get() always returned nil which prevented me from seeing if the underlying value was ever set.

    This PR addresses the issue I ran into.


    The required plugin is viewable here. LMK if there's interest in a PR.

  • README: Add YAML config file to example; add info on file loaders

    README: Add YAML config file to example; add info on file loaders

    As YAML is a widely-used format for config files, it's great to see that uconfig can support it simply by feeding in an existing YAML (un)marshaller. It's not immediately obvious that this is possible, though; adding it to the README examples (and tests, because why not?) should help make it more obvious that it's supported out of the box.

  • Can we not expose the FIELD column in the help document?

    Can we not expose the FIELD column in the help document?

    Can we not expose the FIELD column in the help document? Although the below looks good I don't think its a good idea to reveal how the conf is mapped to an internal data structure. I don't see any configuration library doing that however will leave it to the maintainer

    Supported Fields:
    FIELD                FLAG                  ENV                  DEFAULT                      USAGE
    -----                -----                 -----                -------                      -----
    Hosts                -hosts                HOSTS                localhost,localhost.local    the ip or domains to bind to
    Redis.Address        -redis-address        REDIS_ADDRESS        redis-master                 
    Redis.Port           -redis-port           REDIS_PORT           6379                         
    Redis.Password       -redis-password       REDIS_PASSWORD                                    
    Redis.DB             -redis-db             REDIS_DB             0                            
    Redis.Expire         -redis-expire         REDIS_EXPIRE         5s                           
    Database.Address     -database-address     DATABASE_ADDRESS     localhost                    
    Database.Port        -database-port        DATABASE_PORT        28015                        
    Database.Database    -database-database    DATABASE_DATABASE    my-project    
    
    
  • Adds support for []string

    Adds support for []string

    It's a common scenario to receive slice configs. But there is currently no easy support for that.

    This commit only solves the problem for string slices, although its relatively easy to extend to other types.

    Fixes #4

  • How to use the tag `default:

    How to use the tag `default:""` for [ ]string?

    type Config struct {
      Ports    []string `default:""`
    }
    

    I need to set up a list of strings as default value for "Ports". How can I do this?

    Thanks

  • Semver tags/releases (for Glide support)

    Semver tags/releases (for Glide support)

    I know this is quite a new project, but could you please add tags/releases (using semantic versioning) so that uconfig can be used via Glide without having to pin to specific commits?

A configuration management framework written in Go

Viaduct A configuration management framework written in Go. The framework allows you to write configuration in plain Go, compiled and distributed as a

Dec 14, 2022
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
🛠 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
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
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
Small library to read your configuration from environment variables

envconfig envconfig is a library which allows you to parse your configuration from environment variables and fill an arbitrary struct. See the example

Nov 3, 2022
A minimalist Go configuration library
A minimalist Go configuration library

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 def

Dec 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
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
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
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
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
⚙️ Dead Simple Config Management, load and persist config without having to think about where and how.

Configo Dead Simple Config Management, load and persist config without having to think about where and how. Install go get github.com/UltiRequiem/conf

Apr 6, 2022
Lightweight Go library to use in 12-factor apps.

environ Lightweight Go library to use in 12-factor apps. s, err := environ.E("FOO").AsString() s, err := environ.E("FOO").Default("foo_value").AsStrin

Jan 5, 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
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
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
Manage local application configuration files using templates and data from etcd or consul

confd confd is a lightweight configuration management tool focused on: keeping local configuration files up-to-date using data stored in etcd, consul,

Dec 27, 2022