libuconf

package module
v0.0.0-...-7313c66 Latest Latest
Warning

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

Go to latest
Published: May 3, 2020 License: Unlicense Imports: 8 Imported by: 0

README

= libuconf: your one stop configuration shop

Libuconf is a small go library to handle all sorts of configuration tasks.
It consists of three primary components:

* an extendable scaffolding system for arbitrary configuration systems
* several built-in systems
* several built-in types implementing these systems

If this sounds confusing, don't worry!
As a user you don't need to worry about any of this.
If you're interested in the internals, head over to the "READING" file for a guided source-reading experience.

== Basic Usage
First, create an OptionSet - this is a set of options.
[source, go]
----
optionset := &libuconf.NewOptionSet("MyApp")
----

Then, register some options - the API might remind you of go's built-in flag handling (that's on purpose).
[source, go]
----
var s1, s2, s3 *string
s1 = optionset.String("myflag", 0, "initial value", "myflag help string") <1>
optionset.StringVar(s2, "otherflag", 'o', "different value", "otherflag help string") <2>

opt, s3 := optionset.NewStringOpt("thirdflag", 't', "third value", "help string") <3>
optionset.Var(opt) <4>
----
<1> The 0 here is the null byte - if you set the short option to that, it's considered disabled.
<2> In this example, you can configure s2 with command line flags using `--otherflag` or `-o`.
<3> You can also create the underlying "Option" types.
<4> If you do that, however, you must register them with your OptionSet separately!

Once you're done registering flags, you can parse things!
The built-in methods are ParseFlags, ParseEnv and ParseToml(File(s)|String).
Further invocations overwrite previous ones (see notes).
[source, go]
----
optionset.ParseTomlFile("/etc/app.toml")
optionset.ParseTomlFile("~/.apprc") <1>
optionset.ParseEnv() <2>
err := optionset.ParseFlags(os.Args[1:]) <3>
err = optionset.Parse(os.Args[1:]) <4>
----
<1> If an option is set in both app.toml and .apprc, .apprc will take precedence because it was parsed afterwards.
<2> With the default option types, as in this example, s1 will be configured by the MYAPP_MYFLAG environment variable.
<3> All the Parse* functions actually return error - please check them!
<4> Parse() will parse all of the standard files for your OS, followed by the environment, and finally the cli.

That's it, you're done, all your options should be set now.

== Advanced Usage
Every parsing method ("Env", "Flags", "Toml") is associated with an interface: `EnvOpt`, `FlagOpt` and `TomlOpt` respectively.
All of these include the `Setter` interface, which defines the `Set(interface{}) error` function.

`ParseEnv()` will look for environment variables that start with the capitalized contents of the OptionSet's application name, followed by an underscore and the output of `Env()` of each flag.
`ParseToml*` will run the flag's `Toml()` output as a query against each TOML tree.
Finally, `ParseFlags()` will look for long flags `Flag()` and short flags `ShortFlag()`.
`Bool()` is needed for implicitly setting boolean flags on.
`Usage()` consumes `AppName`, `Help()`, `Get()` and the two `Flag*` functions to generate a usage string - this means it shows you the "current" value in the help string, rather than the default you set.

If you want to add additional configuration sources (such as consul, for example), you would simply define a new interface that includes `Setter` and any functions you need.
Then you would add a new `Parse*` function to `OptionSet` that includes a type assertion (or uses a new Visit* function).

Documentation

Overview

Package libuconf is a small library to handle all sorts of configuration tasks. More specifically, it is an extendable scaffolding system for handling configuration in a unified way, with built-ins to be useful without extending.

Scaffolding

At the core of libuconf is the OptionSet and the interfaces it consumes. Setter is the least common denominator: allowing setting values to options. Beyond that, there are interfaces for each Parse function. For example, the EnvOpt interface provides everything needed by ParseEnv.

Regardless of how many extensions are plugged into libuconf, all you need to do to utilize it is plug a value that implements the needed interfaces into OptionSet.Var(), which will make it available to the Parse family of functions.

Built-In Systems

Libuconf comes with three built-in systems for configuration handling. EnvOpt, used with ParseEnv, FlagOpt, used with ParseFlags, and TomlOpt, used with ParseTomlFile.

Because of how libuconf works, utilizing them for custom values is simple: all you need to do is implement the appropriate interface. For an example, you can look at any of the built-in types.

Built-In Types

Libuconf comes with several types that implement the needed interfaces for the built-in systems. These types are BoolOpt (a boolean option), FloatOpt (a float64 option), HelpOpt (a special help option, only implementing FlagOpt), IntOpt (an int64 option), StringOpt (a string option) and UintOpt (a uint64 option).

All of these built-in types have special integration functions within OptionSet. For example, BoolOpt has OptionSet.Bool and OptionSet.BoolVar. These integration functions, however, are entirely optional. It is entirely valid to create a BoolOpt (or any Opt) by hand, and call OptionSet.Var against it. In fact, this is what half of these integration functions do.

Usage

First, instantiate an OptionSet using NewOptionSet. The argument should be the name of your application. Note that this name is significant! If you use os.Args[0], users will lose their configuration file access if they rename the binary, because AppName is used in ParseStdFiles and Usage. As such, it is recommended to use a constant value for the AppName.

Then, add any options you want. If you are using your own Option types, you should add them using OptionSet.Var. Otherwise, you may take advantage of the integration functions. Note that with the built-in types, the environment variables and configuration file keys searched are derived from the long flag. You can always pass 0 as the shortname to disable the short flag for a flag.

If you want to limit the applicability of some options, you will need to extend libuconf.

Extending - Option Types

To extend libuconf's available options (or de-extend them, restricting parsing) all you need to do is implement the interfaces you want to be used. Feel free to take inspiration from the built-in types. If you want to restrict some string option to only be available in a configuration file, for example, you can copy string.go and remove the functions related to FlagOpt and EnvOpt. Note that you are fully free to do this with no licensing issues, because libuconf is released under the unlicense.

Extending - Systems

To extend libuconf's systems (for example, add support for setting options through consul), there is a bit more work to do.

You will need to subclass OptionSet (or fork libuconf and just add to it). Then, you will need to create a new interface (in this example, ConsulOpt) and a new OptionSet.ParseConsul function. The ParseConsul function should only operate on ConsulOpt members of OptionSet (see ParseEnv for a succint example, implementing a VisitConsul is encouraged) and should only use functions available in ConsulOpt to handle the parsing. This means that ConsulOpt interface should contain everything necessary to perform the work.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoVal = errors.New("missing value")
	ErrSet   = errors.New("failed to set")
)

Base errors that the package might return.

Functions

This section is empty.

Types

type BoolOpt

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

BoolOpt represents a boolean Option.

func NewBoolOpt

func NewBoolOpt(name string, sname rune, val bool, help string) (*BoolOpt, *bool)

NewBoolOpt instantiates a BoolOpt and returns needed implementation details.

func (*BoolOpt) Bool

func (*BoolOpt) Bool() bool

Bool returns whether or not this option is a boolean. This is important because ParseFlags() will handle them differently.

func (*BoolOpt) Env

func (r *BoolOpt) Env() string

Env returns the option's environment search string. For example, if the app name is "APP" and Env() returns "FOO", we will look for the environment variable "APP_FOO".

func (*BoolOpt) Flag

func (r *BoolOpt) Flag() string

Flag returns the long-form flag for this option. All strings are valid, but non-printable ones aren't useful.

func (*BoolOpt) Get

func (r *BoolOpt) Get() interface{}

Get returns the internal value. This is primarily used in Usage() to show the current value for options.

func (*BoolOpt) Help

func (r *BoolOpt) Help() string

Help returns the help string for this option. It is only used in the Usage() call.

func (*BoolOpt) Set

func (r *BoolOpt) Set(vv interface{}) error

Set sets this option's value. It should be able to handle whatever type it might receive, which means it must at least handle strings for being usable in ParseFlags.

func (*BoolOpt) ShortFlag

func (r *BoolOpt) ShortFlag() rune

ShortFlag returns the short-form flag for this option. All runes are valid, but non-printable ones aren't useful. 0 means "disabled".

func (*BoolOpt) Toml

func (r *BoolOpt) Toml() string

Toml returns the option's config file search string. It's passed as-is to toml.Tree.Get().

type EnvOpt

type EnvOpt interface {
	Setter
	Env() string // example: A_B_C
}

EnvOpt describes an option that can be set from the environment.

It is used by ParseEnv() to determine what environment variables to read. For example, if the app name is "APP" and Env() returns "FOO", we will look for the environment variable "APP_FOO".

type FlagOpt

type FlagOpt interface {
	Setter
	Bool() bool
	Flag() string // example: a.b.c
	Help() string
	ShortFlag() rune // can be 0: means disabled; example: x
}

FlagOpt describes an option that can be set using a flag. It is used by ParseFlags.

If Bool returns true, ParseFlags will know that a value is technically optional for the given flag. If it cannot find a value for it, it will thus pass "true" (bool) to Set().

Flag and ShortFlag determine what ParseFlags looks for on the command line, as well as what Usage will print out.

Finally, Help changes the help string in Usage.

type FloatOpt

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

FloatOpt represents a long float Option.

func NewFloatOpt

func NewFloatOpt(name string, sname rune, val float64, help string) (*FloatOpt, *float64)

NewFloatOpt instantiates a FloatOpt and returns needed implementation details.

func (*FloatOpt) Bool

func (*FloatOpt) Bool() bool

Bool returns whether or not this option is a boolean. This is important because ParseFlags() will handle them differently.

func (*FloatOpt) Env

func (r *FloatOpt) Env() string

Env returns the option's environment search string. For example, if the app name is "APP" and Env() returns "FOO", we will look for the environment variable "APP_FOO".

func (*FloatOpt) Flag

func (r *FloatOpt) Flag() string

Flag returns the long-form flag for this option. All strings are valid, but non-printable ones aren't useful.

func (*FloatOpt) Get

func (r *FloatOpt) Get() interface{}

Get returns the internal value. This is primarily used in Usage() to show the current value for options.

func (*FloatOpt) Help

func (r *FloatOpt) Help() string

Help returns the help string for this option. It is only used in the Usage() call.

func (*FloatOpt) Set

func (r *FloatOpt) Set(vv interface{}) error

Set sets this option's value. It should be able to handle whatever type it might receive, which means it must at least handle strings for being usable in ParseFlags.

func (*FloatOpt) ShortFlag

func (r *FloatOpt) ShortFlag() rune

ShortFlag returns the short-form flag for this option. All runes are valid, but non-printable ones aren't useful. 0 means "disabled".

func (*FloatOpt) Toml

func (r *FloatOpt) Toml() string

Toml returns the option's config file search string. It's passed as-is to toml.Tree.Get().

type Getter

type Getter interface {
	Get() interface{}
}

Getter describes an option that can return its *current* value.

This is used in tests, as well as in Usage. Usage in particular allows you to observe the current value of your flags, which is useful to see whether or not your config files (for example) are being applied.

It may also be of interest to consumers of the library, via Visit.

type HelpOpt

type HelpOpt bool

HelpOpt is a special Option to provide -h and --help.

func (*HelpOpt) Bool

func (*HelpOpt) Bool() bool

Bool returns whether or not this option is a boolean. This is important because ParseFlags() will handle them differently.

This is always true for HelpOpt.

func (*HelpOpt) Flag

func (r *HelpOpt) Flag() string

Flag returns the long-form flag for this option. All strings are valid, but non-printable ones aren't useful.

This is always "help" for HelpOpt.

func (*HelpOpt) Help

func (r *HelpOpt) Help() string

Help returns the help string for this option. It is only used in the Usage() call.

It is always "view this help message" for HelpOpt.

func (*HelpOpt) Set

func (r *HelpOpt) Set(vv interface{}) error

Set sets this option's value. It should be able to handle whatever type it might receive, which means it must at least handle strings for being usable in ParseFlags.

It only consumes boolean options, but since it only implements FlagOpt, the only time that will happen is when it's being set implicitly. The side-effect of this is that it will never consume a cli flag value.

func (*HelpOpt) ShortFlag

func (r *HelpOpt) ShortFlag() rune

ShortFlag returns the short-form flag for this option. All runes are valid, but non-printable ones aren't useful. 0 means "disabled".

This is always 'h' for HelpOpt.

type IntOpt

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

IntOpt represents a 64-bit integer Option.

func NewIntOpt

func NewIntOpt(name string, sname rune, val int64, help string) (*IntOpt, *int64)

NewIntOpt instantiates a IntOpt and returns needed implementation details.

func (*IntOpt) Bool

func (*IntOpt) Bool() bool

Bool returns whether or not this option is a boolean. This is important because ParseFlags() will handle them differently.

func (*IntOpt) Env

func (r *IntOpt) Env() string

Env returns the option's environment search string. For example, if the app name is "APP" and Env() returns "FOO", we will look for the environment variable "APP_FOO".

func (*IntOpt) Flag

func (r *IntOpt) Flag() string

Flag returns the long-form flag for this option. All strings are valid, but non-printable ones aren't useful.

func (*IntOpt) Get

func (r *IntOpt) Get() interface{}

Get returns the internal value. This is primarily used in Usage() to show the current value for options.

func (*IntOpt) Help

func (r *IntOpt) Help() string

Help returns the help string for this option. It is only used in the Usage() call.

func (*IntOpt) Set

func (r *IntOpt) Set(vv interface{}) error

Set sets this option's value. It should be able to handle whatever type it might receive, which means it must at least handle strings for being usable in ParseFlags.

func (*IntOpt) ShortFlag

func (r *IntOpt) ShortFlag() rune

ShortFlag returns the short-form flag for this option. All runes are valid, but non-printable ones aren't useful. 0 means "disabled".

func (*IntOpt) Toml

func (r *IntOpt) Toml() string

Toml returns the option's config file search string. It's passed as-is to toml.Tree.Get().

type OptionSet

type OptionSet struct {
	AppName string

	Args []string
	// contains filtered or unexported fields
}

OptionSet represents a set of options.

func NewOptionSet

func NewOptionSet(name string) *OptionSet

NewOptionSet instantiates an OptionSet for a specific application name.

func (*OptionSet) Arg

func (o *OptionSet) Arg(i int) string

Arg is a convenience function for safe access to OptionSet.Args.

func (*OptionSet) Bool

func (o *OptionSet) Bool(name string, sname rune, val bool, help string) *bool

Bool adds a BoolOpt to the OptionSet. It returns a pointer to the output value.

func (*OptionSet) BoolVar

func (o *OptionSet) BoolVar(out *bool, name string, sname rune, val bool, help string)

BoolVar adds a BoolOpt to the OptionSet.

func (*OptionSet) FindLongFlag

func (o *OptionSet) FindLongFlag(s string) (res FlagOpt)

FindLongFlag returns a FlagOpt based on the "Flag" property.

func (*OptionSet) FindShortFlag

func (o *OptionSet) FindShortFlag(c rune) (res FlagOpt)

FindShortFlag returns a FlagOpt based on the "ShortFlag" property.

func (*OptionSet) Float

func (o *OptionSet) Float(name string, sname rune, val float64, help string) *float64

Float adds a FloatOpt to the OptionSet. It returns a pointer to the output value.

func (*OptionSet) FloatVar

func (o *OptionSet) FloatVar(out *float64, name string, sname rune, val float64, help string)

FloatVar adds a FloatOpt to the OptionSet.

func (*OptionSet) Help

func (o *OptionSet) Help() *bool

Help adds --help and -h flags to the OptionSet.

func (*OptionSet) Int

func (o *OptionSet) Int(name string, sname rune, val int64, help string) *int64

Int adds a IntOpt to the OptionSet. It returns a pointer to the output value.

func (*OptionSet) IntVar

func (o *OptionSet) IntVar(out *int64, name string, sname rune, val int64, help string)

IntVar adds a IntOpt to the OptionSet.

func (*OptionSet) Parse

func (o *OptionSet) Parse(ss []string) error

Parse is a wrapper around all the built-in parse methods.

First, it will parse all of the standard files for your platform. It will ignore "file missing" errors, but not any others (e.g setting errors). If it encounters an error in the middle of a file, it will finish parsing the file, but all other files will not be parsed. You will only receive the *last* error in the *first* file that fails.

After that (assuming no errors), it will try to parse your environment. If it encounters an error in your envirnoment, it will still parse the rest. You will only receive the error for the *last* option that failed to be set.

Finally (assuming no errors), it will try to parse your flags (args). See ParseFlags([]string) for more details as to how and when it might error out.

Once all parsing is done, it will check to see if you have a Help flag defined. If you do, and it's set to true, or if there was an error, Parse() will call Usage() for you.

If you want any other behavior, please write your own handling! This is valid and encouraged. I.e this function can also serve as an example as to how to set up your own.

func (*OptionSet) ParseEnv

func (o *OptionSet) ParseEnv() (e error)

ParseEnv will look for environment variables APPNAME_`option.Env()`. If one is found, it will try to set it.

func (*OptionSet) ParseFlags

func (o *OptionSet) ParseFlags(ss []string) error

ParseFlags parses a set of args (ss) and modifies the attached options

These formats are allowed:

-abc value (where a and b are bool types)
-dvalue
--a.b.c=value
--d.e.f value
--g.h.i (where g.h.i is a bool type)

notably missing is -a=value, but you shouldn't need it

Note that non-registered flags are valid. For example, if you did not register a "foobar" flag, "--foobar=y" will be added to Args.

func (*OptionSet) ParseStdToml

func (o *OptionSet) ParseStdToml() error

ParseStdToml parses the standard configuration files for a platform, in order.

func (*OptionSet) ParseTomlFile

func (o *OptionSet) ParseTomlFile(path string) error

ParseTomlFile parses a toml file, looking for options that implement TomlOpt. If there is an error, it is returned, even if it's just a missing file.

func (*OptionSet) ParseTomlFiles

func (o *OptionSet) ParseTomlFiles(paths ...string) error

ParseTomlFiles is a convenience function to run multiple ParseTomlFile(). It also ignores any missing files, unlike ParseTomlFile.

func (*OptionSet) ParseTomlString

func (o *OptionSet) ParseTomlString(c string) error

ParseTomlString parses a string containing TOML data.

func (*OptionSet) String

func (o *OptionSet) String(name string, sname rune, val string, help string) *string

String adds a StringOpt to the OptionSet. It returns a pointer to the output value.

func (*OptionSet) StringVar

func (o *OptionSet) StringVar(out *string, name string, sname rune, val string, help string)

StringVar adds a StringOpt to the OptionSet.

func (*OptionSet) Uint

func (o *OptionSet) Uint(name string, sname rune, val uint64, help string) *uint64

Uint adds a UintOpt to the OptionSet. It returns a pointer to the output value.

func (*OptionSet) UintVar

func (o *OptionSet) UintVar(out *uint64, name string, sname rune, val uint64, help string)

UintVar adds a UintOpt to the OptionSet.

func (*OptionSet) Usage

func (o *OptionSet) Usage()

Usage will use AppName and the Options that are FlagOpts to print usage info.

The format looks like this if there are no short flags:

AppName:
  --flag Really long help
         message.
  --ofl  Other really lon-
         g help message.
  --fl   Help message.

Or like this if there is at least one:

AppName:
  -f, --flag Really long help
             message.
  -o, --of   Other really lon-
             g help message.
      --st   Standalone flag.

func (*OptionSet) Var

func (o *OptionSet) Var(opt Setter)

Var adds an option to the OptionSet. It is expected to be pre-set to its default value.

func (*OptionSet) Visit

func (o *OptionSet) Visit(f func(Setter))

Visit visits each option, passing it to the argument function.

func (*OptionSet) VisitEnv

func (o *OptionSet) VisitEnv(f func(EnvOpt))

VisitEnv visits EnvOpts.

func (*OptionSet) VisitFlag

func (o *OptionSet) VisitFlag(f func(FlagOpt))

VisitFlag visits FlagOpts.

func (*OptionSet) VisitToml

func (o *OptionSet) VisitToml(f func(TomlOpt))

VisitToml visits TomlOpts.

type Setter

type Setter interface {
	Set(interface{}) error
}

Setter describes a type that can be Set. All options must implement Setter.

Set takes an interface, and should use type switch and/or reflection to take the appropriate course of action based on what ended up being passed to it. It is highly recommended to at least handle strings.

If your option implements FlagOpt and Bool returns true, Set is also expected to handle booleans.

type StringOpt

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

StringOpt represents a string Option.

func NewStringOpt

func NewStringOpt(name string, sname rune, val string, help string) (*StringOpt, *string)

NewStringOpt instantiates a StringOpt and returns needed implementation details.

func (*StringOpt) Bool

func (*StringOpt) Bool() bool

Bool returns whether or not this option is a boolean. This is important because ParseFlags() will handle them differently.

func (*StringOpt) Env

func (r *StringOpt) Env() string

Env returns the option's environment search string. For example, if the app name is "APP" and Env() returns "FOO", we will look for the environment variable "APP_FOO".

func (*StringOpt) Flag

func (r *StringOpt) Flag() string

Flag returns the long-form flag for this option. All strings are valid, but non-printable ones aren't useful.

func (*StringOpt) Get

func (r *StringOpt) Get() interface{}

Get returns the internal value. This is primarily used in Usage() to show the current value for options.

func (*StringOpt) Help

func (r *StringOpt) Help() string

Help returns the help string for this option. It is only used in the Usage() call.

func (*StringOpt) Set

func (r *StringOpt) Set(vv interface{}) error

Set sets this option's value. It should be able to handle whatever type it might receive, which means it must at least handle strings for being usable in ParseFlags.

func (*StringOpt) ShortFlag

func (r *StringOpt) ShortFlag() rune

ShortFlag returns the short-form flag for this option. All runes are valid, but non-printable ones aren't useful. 0 means "disabled".

func (*StringOpt) Toml

func (r *StringOpt) Toml() string

Toml returns the option's config file search string. It's passed as-is to toml.Tree.Get().

type TomlOpt

type TomlOpt interface {
	Setter
	Toml() string // a TOML query string; example: a.b.c
}

TomlOpt describes an option that can be set by a value in a TOML file.

The return value of Toml should be the exact search query to plug in. Set will be called with whatever the get call returns (unless it's nil).

type UintOpt

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

UintOpt represents an unsigned 64-bit integer Option.

func NewUintOpt

func NewUintOpt(name string, sname rune, val uint64, help string) (*UintOpt, *uint64)

NewUintOpt instantiates a UintOpt and returns needed implementation details.

func (*UintOpt) Bool

func (*UintOpt) Bool() bool

Bool returns whether or not this option is a boolean. This is important because ParseFlags() will handle them differently.

func (*UintOpt) Env

func (r *UintOpt) Env() string

Env returns the option's environment search string. For example, if the app name is "APP" and Env() returns "FOO", we will look for the environment variable "APP_FOO".

func (*UintOpt) Flag

func (r *UintOpt) Flag() string

Flag returns the long-form flag for this option. All strings are valid, but non-printable ones aren't useful.

func (*UintOpt) Get

func (r *UintOpt) Get() interface{}

Get returns the internal value. This is primarily used in Usage() to show the current value for options.

func (*UintOpt) Help

func (r *UintOpt) Help() string

Help returns the help string for this option. It is only used in the Usage() call.

func (*UintOpt) Set

func (r *UintOpt) Set(vv interface{}) error

Set sets this option's value. It should be able to handle whatever type it might receive, which means it must at least handle strings for being usable in ParseFlags.

func (*UintOpt) ShortFlag

func (r *UintOpt) ShortFlag() rune

ShortFlag returns the short-form flag for this option. All runes are valid, but non-printable ones aren't useful. 0 means "disabled".

func (*UintOpt) Toml

func (r *UintOpt) Toml() string

Toml returns the option's config file search string. It's passed as-is to toml.Tree.Get().

Notes

Bugs

  • llen is hardcoded to 80

Jump to

Keyboard shortcuts

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