Skip to content

Latest commit

 

History

History
217 lines (144 loc) · 6.29 KB

README.md

File metadata and controls

217 lines (144 loc) · 6.29 KB

conf - a configuration parsing lib for Go

Description: A Go library for parsing environment variables (and any other source) and setting corresponding flags. It is heavily inspired by Go's std flag package in its design.

Why

Why another package for parsing the environment? Currently, most popular environment parsing libraries depend on struct tags to map the environment to a structure and provide options like flag requirement or default values when absent.

With conf and the use of Go Generics, we can now have a type-safe API that doesn't depend on struct tags and can take advantage of strong typing.

Let's contrast davidmdm/conf with a popular environment parsing library github.com/kelseyhightower/envconfig:

The envconfig approach is convenient but very sensitive to typos, and the defaults need to be encoded in their string format, which can be error-prone.

package main

import (
    "time"
    "github.com/kelseyhightower/envconfig"
)

type Config struct {
    DatabaseURL string        `envconfig:"DATABASE_URL" required:"true"`
    Timeout     time.Duration `envconfig:"TIMEMOUT" default:"5m"`
}

func main() {
    var cfg Config
    envconfig.Process("", &cfg)
}

On the other hand, davidmdm/conf does not suffer from these problems. It also has the added benefit of being programmatic instead of static. If we need, environment variable names and options could be determined at runtime instead of statically typed into a struct definition.

package main

import (
    "time"
    "github.com/davidmdm/conf"
)

type Config struct {
    DatabaseURL string
    Timeout     time.Duration
}

func main() {
    var cfg Config
    conf.Var(conf.Environ, &cfg.DatabaseURL, "DATABASE_URL", conf.Required[string](true))
    conf.Var(conf.Environ, &cfg.Timeout, "TIMEOUT", conf.Default[time.Duration](5 * time.Minute))

    conf.Environ.MustParse()
}

Overview

This Go package provides a flexible and extensible configuration parser that allows you to easily manage configuration settings in your Go applications. The parser supports environment variables, command line arguments, and file system-based configuration, making it adaptable to various deployment scenarios.

Installation

go get -u github.com/davidmdm/conf

Features

Environment Variables: Retrieve configuration values from environment variables with the ability to set default values and mark certain configurations as required.

Command Line Arguments: Easily map command line flags to configuration variables, supporting case-insensitivity and automatic conversion of underscores to dashes.

File System Configuration: Load configuration settings from files in the file system, providing a convenient way to manage configuration files.

Multiple Sources: Combine any of the above sources or your own custom functions to lookup strings.

Usage

Creating a Parser

To get started, create a configuration parser using the MakeParser function:

import "github.com/davidmdm/conf"

// Create a configuration parser with optional lookup functions. By default if no lookup funcs are provided
// the parser will use os.Lookupenv
parser := conf.MakeParser()

You can provide one or more lookup functions to the MakeParser function, which will be used to retrieve configuration values.

Define your configuration variables using the Var function:

var (
    yourStringVar string
    yourIntVar    int
)

conf.Var(parser, &yourStringVar, "YOUR_STRING_VAR", conf.Required[string](true))
conf.Var(parser, &yourIntVar, "YOUR_INT_VAR", conf.Default[int](42))

// In this example, YOUR_STRING_VAR is a required string variable, and YOUR_INT_VAR is an optional integer variable with a default value of 42.

Parsing Configuration

Parse the configuration using the Parse or MustParse methods:

if err := parser.Parse(); err != nil {
// Handle configuration parsing errors
}

// Alternatively, use MustParse to panic on errors
parser.MustParse()

Configuring Lookup Functions

Environment Variables

The package provides a default parser for environment variables conf.Environ. You can create one yourself:

environ := conf.MakeParser(os.Lookupenv)

Command Line Arguments

Create a lookup function for command line arguments:

var (
    path string
    max  int
)

args := conf.MakeParser(conf.CommandLineArgs())

conf.Var(args, "path", &path)
conf.Var(args, "max", &max)

args.MustParse()

File System Configuration

Create a lookup function for file system-based configuration:

var (
    secret string
)

fs := conf.MakeParser(conf.FileSystem(conf.FileSystemOptions{Base: "/path/to/config/files"}))
conf.Var(fs, "secret.txt", &secret)

fs.MustParse()

User provided lookups

When creating a parser any number of lookup functions can be provided. For example you could read key/value pairs from maps, from a redis instance or any other key/value store.

Let's implement a Redis integration that isn't provided by conf:

var redisURL string
conf.Var(conf.Environ, "REDIS_URL", &redisURL, config.Required[string](true))

config.Environ.MustParse()

// Skipping error handling for example's sake
opt, _ := redis.ParseURL(redisURL)

client := redis.NewClient(opt)

rdb := conf.MakeParser(func(key string) (string, bool) {
    value, err := rdb.Get(ctx, key)
    if err != nil {
        if err == redis.Nil {
            return "", false
        }
        panic(err) // panics in lookup functions are recovered during parsing and presented as normal errors from Parse().
    }
    return value, true
})

conf.Var(rdb, ...)

rdb.MustParse()

Multi Source Lookups

You can pass more than one lookup function when creating a parser. It will look search each source in turn and attempt to use the first value it finds.

// First Lookup command line args, then fallback to os.Lookupenv
sources := conf.MakeParser(conf.CommandLineArgs(), os.Lookupenv)

var max int

// Note that commandline args automatically lower-cases and converts underscores to dashes before performing a lookup. This allows it to play nicely os.Lookupenv and allow you to override environment variables via command line args.
conf.Var(sources, &max, "MAX") // Can be configured via --max flag or MAX environment variable
sources.MustParse()

License

This project is licensed under the MIT License - see the LICENSE file for details