config

package module
v2.1.4 Latest Latest
Warning

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

Go to latest
Published: Mar 14, 2021 License: MIT Imports: 7 Imported by: 8

README

GoDoc Build Status Go Report Card Coverage Status Awesome

Config

GoLobby Config is a lightweight yet powerful config package for Go projects. It takes advantage of env files and OS variables alongside config files to be your ultimate requirement.

Documentation

Required Go Version

It requires Go v1.11 or newer versions.

Installation

To install this package run the following command in the root of your project

go get github.com/golobby/config/v2
Getting Started

The following example demonstrates how to set and get a simple configuration key/value.

c, err := config.New()
// Check error...

c.Set("name", "Pink Floyd")

name, err := c.Get("name")
Feeders

Feeders provide the configuration contents. The Config package supports the following feeders out of the box.

  • Map Feeds using a simple map[string]interface{}.
  • Json Feeds using a JSON file.
  • JsonDirectory Feeds using a directory of JSON files.
  • Yaml Feeds using a YAML file.
  • YamlDirectory Feeds using a directory of YAML files.
  • Env Feeds using an environment file.
  • OS Feeds using a list of OS variables.

Of course, you can implement your custom feeders by implementing the Feeder interface.

Pass feeders to the New() method like the following example.

f := feeder.Map{"name": "Pink Floyd"}

c, err := config.New(f)
name, err := c.Get("name") // "Pink Floyd"

Or you can pass multiple feeders like this example:

f1 := feeder.Map{"name": "Divison Bell"}
f2 := feeder.Map{"year": 1994}

c, err := config.New(f1, f2)
name, err := c.Get("name") // "Pink Floyd"
name, err := c.Get("year") // 1994
Feeding using Map

You don't like config files!? It's OK you can use the Map feeder like this example:

c, err := config.New(feeder.Map{
    "name": "Hey You",
    "band": "Pink Floyd",
    "year": 1979,
    "rate": 4.6,
    "like": true,
})

name, err := c.Get("name")
// OR
name, err := c.GetString("name")

year, err := c.Get("year")
// OR
year, err := c.GetInt("year")

rate, err := c.Get("rate")
// OR
rate, err := c.GetFloat("rate")

rate, err := c.Get("like")
// OR
rate, err := c.GetBool("like")
// OR
rate, err := c.GetStrictBool("like")
Feeding using Json

Storing configuration data in a JSON file could be a brilliant idea. The example below shows how to use the Json feeder.

JSON file: https://github.com/golobby/config/blob/v2/feeder/test/config.json

Go code:

c, err := config.New(feeder.Json{Path: "path/to/config.json"})

v, err := c.GetFloat("version")         // 3.14
v, err := c.GetInt("numbers.2")         // 3
v, err := c.Get("users.0.address.city") // Delfan
Feeding using JsonDirectory

You might have many configuration data and it doesn't fit in a single JSON file. In this case, you can use multiple JSON files and feed them using JsonDirectory feeder like this example:

Sample project config directory:

- main.go
- config
- - app.json
- - db.json

JSON directory: https://github.com/golobby/config/tree/v2/feeder/test/json

Go code:

c, err := config.New(feeder.JsonDirectory{Path: "path/to/config"})

v, err := c.GetFloat("app.version")     // 3.14
v, err := c.GetString("db.mysql.host")  // localhost
Feeding using Yaml

YAML files are a trend these days, so why not store configurations in them?

YAML file: https://github.com/golobby/config/blob/v2/feeder/test/config.yaml

Go code:

c, err := config.New(feeder.Yaml{Path: "path/to/config.yaml"})

v, err := c.GetFloat("version")         // 3.14
v, err := c.GetInt("numbers.2")         // 3
v, err := c.Get("users.0.address.city") // Delfan
Feeding using YamlDirectory

You might have many configuration data and it doesn't fit in a single YAML file. In this case, you can use multiple YAML files and feed them using YamlDirectory feeder like this example:

Sample project config directory:

- main.go
- config
- - app.yaml
- - db.yaml

Yaml directory: https://github.com/golobby/config/tree/v2/feeder/test/yaml

Go code:

c, err := config.New(feeder.YamlDirectory{Path: "path/to/config"})

v, err := c.GetFloat("app.version")     // 3.14
v, err := c.GetString("db.mysql.host")  // localhost
Feeding using Env

An environment file could be a main or a secondary feeder to override other feeder values.

Because of different key names in env files, their names would be updated this way:

  • APP_NAME => app.name
  • DB_MYSQL_HOST => db.mysql.host

ENV file: https://github.com/golobby/config/blob/v2/feeder/test/.env

Go code:

c, err := config.New(feeder.Env{Path: "path/to/.env"})

v, err := c.GetString("url")     // https://example.com (Original Key: URL)
v, err := c.GetString("db.host") // 127.0.0.1 (Original Key: DB_HOST)

Env feeder fetches operating system variables when the value is empty.

Go code:

// Set an OS variable
_ = os.Setenv("APP_NAME", "MyAppUsingConfig")

c, err := config.New(feeder.Env{Path: "path/to/.env"})

v, err := c.Get("app.name") // MyAppUsingConfig (empty in .env ==> OS variable)

You can disable this feature this way:

// Set an OS variable
_ = os.Setenv("APP_NAME", "MyAppUsingConfig")

c, err := config.New(feeder.Env{Path: "test/.env", DisableOSVariables: true})

v, err := c.Get("app.name") // "" (empty as in .env)
Feeding using OS

There is another feeder named OS that fetches OS variables and updates variable names like Env feeder. You should use OS feeders to override other feeders like Env, Json and Yaml feeders.

// Set an OS variable
_ = os.Setenv("APP_NAME", "MyAppUsingConfig")
_ = os.Setenv("APP_VERSION", "3.14")

c, err := config.New(OS{Variables: []string{"APP_NAME", "APP_VERSION", "APP_EMPTY"}})

v, err := c.Get("app.name")     // "MyAppUsingConfig"
v, err := c.Get("app.version")  // 3.14
v, err := c.Get("app.empty")    // ""
v, err := c.Get("app.new")      // ERROR!
Multiple Feeders

One of the key features in the Config package is feeding using multiple feeders. Lately added feeders will override early added ones.

c, err := config.New(
    feeder.Map{
        "name": "MyAppUsingConfig"
        "url": "going to be overridden by the next feeders",
    },
    feeder.Map{
        "version": 3.14
        "url": "going to be overridden by the next feeder",
    },
    feeder.Map{
        "url": "https://github.com/golobby/config",
    },
)

v, err := c.Get("name")     // "MyAppUsingConfig"
v, err := c.Get("version")  // 3.14
v, err := c.Get("url")      // "https://github.com/golobby/config"
A Sample using Json and Env feeders and OS variables

path/to/config/app.json:

{
  "name": "MyAppUsingConfig",
  "version": 3.14,
  "url": "http://localhost"
}

path/to/config/db.json:

{
  "mysql": {
    "host": "127.0.0.1",
    "user": "root",
    "pass": "secret"
  }
}

.env:

APP_URL=https://github.com/golobby/config
DB_MYSQL_HOST=192.168.0.1
DB_MYSQL_PASS=

Go code:

_ = os.Setenv("APP_URL", "http://192.168.0.1")
_ = os.Setenv("DB_MYSQL_PASS", "password")

c, err := config.New(
    feeder.JsonDirectory{Path: "path/to/config"},
    feeder.Env{Path: ".env"}
)

v, err := c.Get("app.name")
// "MyAppUsingConfig" (from path/to/config/app.json)

v, err := c.Get("app.version")
// 3.14 (from path/to/config/app.json)

v, err := c.Get("app.url")
// "https://github.com/golobby/config" (from .env)
// APP_URL exists and it's not empty in .env so the Env feeder doesn't load it from OS variables.
// The value from .env overrides the value in the app.json file

v, err := c.Get("db.mysql.host")
// "192.168.0.1" (from .env)
// DB_MYSQL_HOST in .env overrides the value in the db.json file

v, err := c.Get("db.mysql.user")
// "root" (from path/to/config/app.json)

v, err := c.Get("db.mysql.pass")
// "password" (from OS variables)
// The key exists in .env but it's empty so the Env feeder loads it
// from OS variables (This feature is on in default) and override the value in the db.json file 
Reload the feeders

One of the benefits of using config management tools is the ability to update the configurations without redeployment. The Config package takes advantage of OS signals to handle this requirement. It listens to the "SIGHUP" signal and reloads the config files (feeders) on receive.

You can send this signal to your application with the following shell command:

KILL -SIGHUP [YOUR-APP-PROCESS-ID]

To get your application process id you can use the ps shell command.

Strict Type Values

When you use the Get() method you have to cast the returned value type before using it. You can use the following methods, instead.

  • GetString() returns only string values
  • GetInt() returns only int and float values (pruning the floating part)
  • GetFloat() returns only float and int values (in float64 type)
  • GetBool() returns true, "true" and 1 as true, and false, "false" and 0 as false
  • GetStrictBool() returns only boolean values (true and false)

License

GoLobby Config is released under the MIT License.

Documentation

Overview

Package Config is a lightweight yet powerful configuration management tool for Go projects. It takes advantage of env files and OS variables alongside Config files to be your only requirement.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config keeps all the Config instance data.

func New

func New(feeders ...Feeder) (*Config, error)

New makes a brand new instance of Config with the given feeders.

func (*Config) Feed

func (c *Config) Feed(f Feeder) error

Feed takes a feeder and feeds the instance with it. The built-in feeders are in the feeder sub-package.

func (*Config) Get

func (c *Config) Get(key string) (interface{}, error)

Get returns the value of the given key. The return type is "interface{}". It probably needs to be cast to the related data type. It returns an error if there is no value for the given key.

func (*Config) GetAll

func (c *Config) GetAll() map[string]interface{}

GetAll returns all the configuration items (key/values).

func (*Config) GetBool

func (c *Config) GetBool(key string) (bool, error)

GetBool returns the value of the given key. It also casts the value type to bool internally. It converts the "true", "false", 1 and 0 values to related boolean values. It returns an error if the related value is not a bool. It returns an error if there is no value for the given key.

func (*Config) GetFloat

func (c *Config) GetFloat(key string) (float64, error)

GetFloat returns the value of the given key. It also casts the value type to float64 internally. It returns an error if the related value is not a float64. It returns an error if there is no value for the given key.

func (*Config) GetInt

func (c *Config) GetInt(key string) (int, error)

GetInt returns the value of the given key. It also casts the value type to int internally. It returns an error if the related value is not an int. It returns an error if there is no value for the given key.

func (*Config) GetStrictBool

func (c *Config) GetStrictBool(key string) (bool, error)

GetStrictBool returns the value of the given key. It also casts the value type to bool internally. It doesn't convert the "true" and "false" string values to related boolean values. It returns an error if the related value is not a bool. It returns an error if there is no value for the given key.

func (*Config) GetString

func (c *Config) GetString(key string) (string, error)

GetString returns the value of the given key. It also casts the value type to string internally. It returns an error if the related value is not a string. It returns an error if there is no value for the given key.

func (*Config) Reload

func (c *Config) Reload() error

Reload reloads all the added feeders and applies new changes.

func (*Config) Set

func (c *Config) Set(key string, value interface{})

Set stores the given key/value into the Config instance. It keeps all the changes in memory and won't change the Config files.

func (*Config) StartListener

func (c *Config) StartListener()

StartListener makes the instance to listen to the SIGHUP and reload the feeders.

type Feeder

type Feeder interface {
	Feed() (map[string]interface{}, error)
}

Feeder is an interface for config feeders that provide content of a config instance.

type NotFoundError

type NotFoundError struct {
	// contains filtered or unexported fields
}

NotFoundError happens when it cannot find the requested key.

func (*NotFoundError) Error

func (n *NotFoundError) Error() string

type TypeError

type TypeError struct {
	// contains filtered or unexported fields
}

TypeError happens when it cannot cast a value to the requested type.

func (*TypeError) Error

func (t *TypeError) Error() string

Directories

Path Synopsis
Package feeder is a collection of feeders
Package feeder is a collection of feeders

Jump to

Keyboard shortcuts

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