confy

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2024 License: MIT Imports: 20 Imported by: 0

README

Confy

confy is your one stop shop for configuration, it allows configuration from multiple sources including command-line arguments, environment variables, and configuration files in various formats (JSON, YAML, TOML).

Features

  • Multiple Configuration Sources: Populate settings from CLI flags, environment variables, and config files.
  • Automatic CLI Flag and Env Variable Mapping: Fields are mapped automatically and can be renamed with the confy:"" tag
  • Support for YAML, JSON, and TOML: Automatically detect and parse configuration file format, no added effort to switch to a new format

Installation

go get github.com/NHAS/confy

Usage

Tags
  • confy:"field_name;sensitive": Customize field names for env variables, CLI flags, and config files.
  • confy_description:"Field Description here": Set field descriptions for CLI parsing and help messages.
Basic Examples

config.json:

{
  "Database": {
    "Host": "localhost",
    "Port": 5432,
    "User": "dbuser",
    "Password": "securepassword"
  },
  "new_name": "some_value"
}

config.yaml:

Database:
  Host: "localhost"
  Port: 5432
  User: "dbuser"
  Password: "securepassword"

new_name: "some_value"
package main

import (
	"fmt"
	"github.com/NHAS/confy"
)

type Config struct {
	Database struct {
		Host     string
		Port     int
		User     string
		Password string
	}

    Renamed string `confy:"new_name"`
}

func main() {
    // Defaults will also load from env and cli!
	loadedConfig, _, err := confy.Config[Config](confy.Defaults("config.json"))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

	fmt.Printf("Loaded JSON config: %+v\n", loadedConfig)

    yamlLoadedConfig, _, err := confy.Config[Config](confy.Defaults("config.yaml"))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

    fmt.Printf("Loaded YAML config: %+v\n", yamlLoadedConfig)

    // They're the same!
    
}

Output

Loaded config: {Database:{Host:localhost Port:5432 User:dbuser Password:securepassword} Renamed:some_value}
Loaded config: {Database:{Host:localhost Port:5432 User:dbuser Password:securepassword} Renamed:some_value}
Environment Variables

For struct:

package main

import (
    "fmt"
    "github.com/NHAS/confy"
)

type Config struct {
    Server struct {
        Host string
    }
}

func main() {
	populatedConfig, _, err := confy.Config[Config](confy.FromEnvs(confy.DefaultENVDelimiter))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

    fmt.Println(populatedConfig.Server.Host)
}

Expected environment variable:

export Server_Host="localhost"
$ ./test
localhost
CLI Flags only

For struct:

package main

import (
    "fmt"
    "github.com/NHAS/confy"
)

type Config struct {
    Database struct {
        Port int
    }
}

func main() {
	populatedConfig, _, err := confy.Config[Config](confy.FromCli(confy.DefaultCliDelimiter))
	if err != nil {
		fmt.Println("Error loading config:", err)
		return
	}

    fmt.Println(populatedConfig.Database.Port)
}

Expected CLI flag:

$ ./app -Database.Port=5432
5432

Logging

Confy has logging capabilities using the slog package. Use the WithLogLevel option to adjust verbosity or disable logging.

Configuration Options

Confy offers a variety of options for configuring your application's settings.

Option Description
Defaults(...) Loads configurations in the order: config file -> environment variables -> CLI flags. This sets a non-strict parsing mode for unknown fields in the config file.
FromConfigFile(...) Load configuration from a file. Supports YAML, JSON, and TOML.
FromConfigBytes(...) Load configuration from raw bytes, ideal for embedding configuration in code.
FromConfigURL(...) Load configuration from URL. Supports YAML, JSON, and TOML, use extension or content type to specify type when using auto keyword
FromConfigFileFlagPath(...) Load configuration from file with filepath specified as cli flag
WithStrictParsing(...) Parse config files in a strict way, do not allow unknown fields
FromCli(...) Load configuration from CLI flags. Set a delimiter for nested struct parsing.
WithLogLevel(...) Set logging level to control output verbosity. Useful for debugging.
WithCliTransform(...) Takes a function to run against the generated CLI flag name, allows you to modify the flag name
WithEnvTransform(...) Takes a function to run against the generated ENV variable name, allows you to modify the ENV name

Notes

  • Complex structures must implement encoding.TextUnmarshaler and encoding.TextMarshaler for CLI/ENV parsing.
  • CLI flags and environment variables use the delimiters (. for CLI, _ for ENV by default) when handling nested fields.

Documentation

Index

Constants

View Source
const (
	// The default delimiter used for environment variable search
	ENVDelimiter = "_"
	// the default delimiter used for cli flag construction
	CLIDelimiter = "."

	LoggingDisabled = math.MaxInt
)

Variables

This section is empty.

Functions

func Config

func Config[T any](suppliedOptions ...OptionFunc) (result T, warnings []error, err error)

Config[T any] takes a structure and populates the exported fields from multiple configurable sources. parameters:

config T; A structure to populate suppliedOptions ...option: Various options that can be used, disabling configuration sources etc

return:

result T: The populated configuration file warnings []error: Non-fatal errors, but should be at least printed err error: Fatal errors while parsing/extracting/populating the configuration file

Sources:

  • CLI using the "flag" package
  • Environment Variables using os.Getenv(...)
  • Configuration File using filepath or raw bytes, this supports yaml, json and toml so your configuration can file can be any of those types

Tags Confy defines two flags:

  • confy:"field_name;sensitive" The "confy" tag is used to rename the field, meaning changing what env variables, cli flags and configuration file/bytes fields to look for

  • confy_description:"Field Description here" Sets the description of a field when being added to cli parsing, so when using -confy-help (or entering an invalid flag) it will so a good description

Important Note:

Configuring from Envs or CLI flags is more difficult for complex types (like structures)
As such to unmarshal very complex structs, or structs with private members, the struct must implement encoding.TextUnmarshaler and encoding.TextMarshaler to work properly

CLI Confy will automatically register flags from the configuration file structure and parse os.Args when FromCli is supplied as an option (or defaults are used) flags will be in the following format:

 struct {
    Thing string
       Nested struct {
		   NestedField string
	   }
 }

 would look for environment variables:
 -Thing
 -Nested_NestedField

ENV

 struct {
    Thing string
       Nested struct {
		   NestedField string
	   }
 }

 would look for environment variables:
 Thing
 Nested_NestedField

func GetGeneratedCliFlags

func GetGeneratedCliFlags[T any](delimiter string) []string

GetGeneratedCliFlags return list of auto generated cli flag names that LoadCli/Config will check

func GetGeneratedCliFlagsWithTransform

func GetGeneratedCliFlagsWithTransform[T any](delimiter string, transformFunc Transform) []string

GetGeneratedCliFlagsWithTransform return list of auto generated cli flag names that LoadEnv/Config will check it optionally also takes a transform func that you can use to change the flag name

func GetGeneratedEnv

func GetGeneratedEnv[T any](delimiter string) []string

GetGeneratedEnv return list of auto generated environment variable names that LoadEnv/Config will check

func GetGeneratedEnvWithTransform

func GetGeneratedEnvWithTransform[T any](delimiter string, transformFunc Transform) []string

GetGeneratedEnvWithTransform return list of auto generated environment variable names that LoadEnv/Config will check it optionally also takes a transform func that you can use to change the env name

func LoadCli

func LoadCli[T any](delimiter string) (result T, err error)

LoadCli populates a configuration file T from cli arguments

func LoadCliWithTransform

func LoadCliWithTransform[T any](delimiter string, transform func(string) string) (result T, err error)

LoadCli populates a configuration file T from cli arguments and uses the transform to change the name of the cli flag

func LoadConfigBytes

func LoadConfigBytes[T any](data []byte, strict bool, configType ConfigType) (result T, err error)

LoadConfigBytes loads a configuration from yaml, json or toml bytes and returns the populated structure

func LoadConfigFile

func LoadConfigFile[T any](path string, strict bool, configType ConfigType) (result T, err error)

LoadConfigFile loads a yaml, json or toml file from path and returns the populated structure

func LoadConfigFileAuto

func LoadConfigFileAuto[T any](path string, strict bool) (result T, err error)

LoadConfigFileAuto loads a yaml, json or toml file from path and returns the populated structure sets automatic file type determination

func LoadEnv

func LoadEnv[T any](delimiter string) (result T, err error)

LoadEnv populates a configuration file T from environment variables

func LoadEnvWithTransform

func LoadEnvWithTransform[T any](delimiter string, transform func(string) string) (result T, err error)

LoadEnvWithTransform populates a configuration file T from env variables and uses the transform to change the name of the environment variable

Types

type ConfigType

type ConfigType string
const (
	Yaml ConfigType = "yaml"
	Json ConfigType = "json"
	Toml ConfigType = "toml"
	Auto ConfigType = "auto"
)

type OptionFunc

type OptionFunc func(*options) error

func Defaults

func Defaults(cliFlag, defaultPath string) OptionFunc

Defaults adds all three configuration determination options as on. The configs struct will be configured config file -> envs -> cli, so that cli takes precedence over more static options, for ease of user configuration. The config file will be parsed in a non-strict way (unknown fields will just be ignored) and the config file type is automatically determined from extension (supports yaml, toml and json), if you want to change this, add the FromConfigFile(...) option after Defaults(...) cliFlag string : cli flag that holds the config path defaultPath string: if the cli flag is not defined, used this as the default path to load config from

func DefaultsFromPath

func DefaultsFromPath(path string) OptionFunc

DefaultsFromPath adds all three configuration determination sources. The configs struct will be configured config file -> envs -> cli, so that cli takes precedence over more static options, for ease of user configuration. The config file will be parsed in a non-strict way (unknown fields will just be ignored) and the config file type is automatically determined from extension (supports yaml, toml and json), if you want to change this, add the FromConfigFile(...) option after Defaults(...) path string : config file path

func FromCli

func FromCli(delimiter string) OptionFunc

FromCli will automatically look for configuration variables from CLI flags delimiter: string when looking for cli flags this string should be used for denoting nested structures e.g

 delimiter = .
 struct {
    Thing string
       Nested struct {
		   NestedField string
	   }
 }

 would look for CLI flags:
 -Thing
 -Nested_NestedField

 Configuring from Cli cannot be as comprehensive for complex types (like structures) as using the configuration file.
 To unmarshal very complex structs, the struct must implement encoding.TextUnmarshaler and encoding.TextMarshaler

func FromConfigBytes

func FromConfigBytes(data []byte, configType ConfigType) OptionFunc

FromConfigBytes tells confy to load a config file from raw bytes data: []byte config file raw bytes configType: ConfigType, what type the config bytes are supports yaml, toml and json, the Auto configuration will return an error

func FromConfigFile

func FromConfigFile(path string, configType ConfigType) OptionFunc

FromConfigFile tells confy to load a config file from path path: string config file path configType: ConfigType, what type the config file is expected to be, use `Auto` if you dont care and just want it to choose for you. Supports yaml, toml and json

func FromConfigFileFlagPath

func FromConfigFileFlagPath(cliFlagName, defaultPath, description string, configType ConfigType) OptionFunc

FromConfigFileFlagPath tells confy to load file from path as specified by cli flag cliFlagName: string cli option that defines config filepath configType: ConfigType, what type the config file is expected to be, use `Auto` if you dont care and just want it to choose for you. Supports yaml, toml and json

func FromConfigURL

func FromConfigURL(urlOpt string, configType ConfigType) OptionFunc

FromConfigURL tells confy to load file from a url (http/https) url: string url of configuration file configType: ConfigType, what type the config file is expected to be, use `Auto` if you dont care and just want it to choose for you. Supports yaml, toml and json

func FromEnvs

func FromEnvs(delimiter string) OptionFunc

FromEnvs sets confy to automatically populate the configuration structure from environment variables delimiter: string when looking for environment variables this string should be used for denoting nested structures e.g

 delimiter = _
 struct {
    Thing string
       Nested struct {
		   NestedField string
	   }
 }

 would look for environment variables:
 Thing
 Nested_NestedField

 Configuring from Envs cannot be as comprehensive for complex types (like structures) as using the configuration file.
 To unmarshal very complex structs, the struct must implement encoding.TextUnmarshaler

func WithCliTransform

func WithCliTransform(t Transform) OptionFunc

WithCliTransform runs the auto generated cli flag name through function t(generated string)string allowing you to change the flag name if required

E.g

transformFunc := func(flag string)string {
   return strings.ToUpper(flag)
}

WithCliTransform(transformFunc) results in cli flag names that are all upper case

func WithConfigRequired

func WithConfigRequired() OptionFunc

WithConfigRequired causes failure to load the configuration from file/bytes/url to become fatal rather than just warning

func WithEnvTransform

func WithEnvTransform(t Transform) OptionFunc

WithEnvTransform runs the auto generated env through function t(generated string)string allowing you to change the env variable name if required

E.g

transformFunc := func(env string)string {
   return strings.ToUpper(env)
}

WithCliTransform(transformFunc) results searching for env variables that are all upper case

func WithLogLevel

func WithLogLevel(logLevel slog.Level) OptionFunc

WithLogLevel sets the current slog output level Defaulty logging is disabled Very useful for debugging

func WithNonStructCliFlag

func WithNonStructCliFlag() OptionFunc

func WithStrictParsing

func WithStrictParsing() OptionFunc

WithStrictParsing parse config files in a strict way, do not allow unknown fields

type TextSlice

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

func (*TextSlice) Set

func (s *TextSlice) Set(value string) error

func (*TextSlice) String

func (s *TextSlice) String() string

type Transform

type Transform func(generated string) string

Jump to

Keyboard shortcuts

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