panfigure

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Apr 16, 2025 License: Apache-2.0 Imports: 10 Imported by: 0

README

* Panfigure

An opinionated, declarative configuration utility for Go CLI applications, using Viper/Cobra.
Panfigure relies completely on Viper, and on Cobra for CLI options.
The point of the library is to ease the process of creating a configuration that is from multiple sources (file, environment, and CLI) and cascades in a predictable way.

It also provides configuration status output including the value for each config as well as the source that provided it.

** Usage
The library allows configuration through:

 1. CLI flags
 2. Environment variables
 3. config file

	Flags take precendence over ENV, which takes precedence over the config files.

	The convention for setting values begins with the key in the config file, which is all lowercase, underscore separated.  The ENV VAR is all uppercase, underscore separated, and begin with a prefix.  The CLI options are all lowercase, hyphen separated, POSIX style.

*** Quickstart
The bones of your configuration are ~CommandOptions~.  See the examples folder for some ideas of what that can look like.

Once commands and options are created, you can run a very simple application that displays all detected configurations in the terminal:

See all the keys that you've configured with:

#+begin_src go
  package main

  import (
	  "log"

	  "github.com/polyglotlabs/panfigure"
	  "github.com/spf13/cobra"
  )

  func main() {
	  cobra.CheckErr(panfigure.Configure())
	  status := panfigure.StatusTable([]string{})
	  log.Println(status)
  }
#+end_src


*** The CommandOptions type
panfigure.CommandOptions declare the configuration parameters available to a cobra.Command.

TODO enumerate important fields.

See examples.

*** File Configuration
Panfigure allows reading of all configuration keys from a file (of any type supported by Viper).
/Keys are nested under the subcommands that they apply to!/
So configurations that are applied to the root command are not nested.  For example:

In command like ~myapp --verbose start --host localhost~

The keys in viper will be ~verbose~  and ~start.host~.

Using configuration files requires some small setup in your application:

1. declare search paths for config file
2. optionally declare a config file type eg. JSON
3. declare config file names

   #+begin_src go
	 // in order search these directories until a config file is found
	 configPaths := []string{
		 "/etc/myapp",
		 "$HOME/.myapp",
		 ".",
	 }

	 // config_paths is a special config, reserved by panfigure for your convenience
	 viper.Set("config_paths", configPaths)
	 // OR
	 viper.AddConfigPath("/etc/myapp")

	 viper.SetConfigType("json")
	 panfigure.UseConfigFile("name-of-config")

	 // multiple values are acceptable - both will be searched
	 panfigure.UseConfigFile("also-use-this-config-file")

	 // if viper.SetConfigType is not called
	 panfigure.UseConfigFile("name-of-config.yml")
   #+end_src

Once set up panfigure will read all config files and merge them together in the order declared.

Since the intent of panfigure is to ease the setup of these configurations, the ~config_paths~ key is reserved for this purpose, if you like.  This makes it easy to pass the ~--config-paths~ CLI option to set this value at runtime if desired.  See ~examples/reserved_keys.go~  Otherwise it can be set programatically as above.

All filetypes supported by Viper will be supported here.

If no config paths are provided, panfigure will not look for any config files.

If no config files are provided, file configuration will not be used.

*** Environment Configuration

Environment configuration is a simple wrapper for ~viper.AutomaticEnv~ and will lazy load all defined configs found in the environment, optionally with env_prefix.  If no env_prefix is provided, Viper will attempt to find an exact match.

Because of the nesting capabilities of panfigure, the keys are delimited with ~.~.
panfigure replacers those with ~_~ for purposes of ENV vars.

For example using env_prefix ~MYAPP~:
~start.host~ will correspond to ~MYAPP_START_HOST~
~verbose~ will correspond to ~MYAPP_VERBOSE~

panfigure adds the following functionality:

1. Keeps track of configs found in the environment for reporting via status
2. Reserves another viper key ~env_prefix~.  Exactly the same as ~config_paths~.  This allows simple runtime configuration of env_prefix if desired.  See ~examples/reserved_keys.go~

*** Accessing Configurations in your Application

Once your commands are created, all configuration values are accessible on the global Viper instance.  All packages in your go modules will be able to access these configurations with (using examples above):

#+begin_src go
  host := viper.Get("start.host")
  // OR
  host := viper.GetString("start.host")

  verbose := viper.Get("verbose")
  // OR
  verbose := viper.GetBool("verbose")
#+end_src

See examples for more.

Documentation

Index

Constants

View Source
const (
	STATUS_NOT_FOUND = "not found"
)

Variables

This section is empty.

Functions

func Cli

func Cli() error

Cli binds flags that have been configured as CommandOptions. Viper is the source of truth for all configuration. Cobra is only for reading in subcommands and cli flags and handling help display.

func Configure

func Configure() error

Configure triggers the reading of the configuration from all sources.

func Env

func Env()

Env is a wrapper for viper.AutomaticEnv. It will use env_prefix if available.

func Reload

func Reload() error

Reload discards any existing configuration and reloads from new sources

func SetCommandOptions

func SetCommandOptions(c *cobra.Command, opts []*CommandOptions)

SetCommandOptions adds a cobra command with configuration options to the list for configuration by viper.

func SetRootCommand

func SetRootCommand(c *cobra.Command)

SetRootCommand allows panfigure access to the root cobra command from of an application.

func StatusTable

func StatusTable(keys []string) string

StatusTable returns a text table, somewhat suitable for display in terminal, containing requested keys with values and sources.

func UseConfigFile

func UseConfigFile(name string) error

Types

type CommandOptions

type CommandOptions struct {
	LongOpt, ShortOpt, OptName, Description, OptType string

	// NotImplemented is for options that have been begun aren't yet useful
	NotImplemented,

	NoCLI,

	Persistent, Required bool
	DefaultValue interface{}
}

CommandOptions are used to declare the configuration options for an application. They are most closely related to cobra.Command, but also define behavior for Env and file-based configs.

func (*CommandOptions) Name

func (c *CommandOptions) Name() string

Name produces a name for the config value in Viper (and files) based on the LongOpt name, if a specific name is not provided.

type Metadata

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

Metadata is information that won't be used by the application, but might be interesting to the user, eg. through Status functions.

func (*Metadata) GetSource

func (m *Metadata) GetSource(key string) string

GetSource returns a description of where a setting was configured. Possible values: default, env, file(name), cli, unknown*

type StatusError

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

func (*StatusError) Error

func (s *StatusError) Error() string

type StatusInfo

type StatusInfo struct {
	Key, Source string
	Value       interface{}
	Err         error
}

func Status

func Status(keys []string) []*StatusInfo

Status returns StatusInfo for the requested keys. If an empty slice is passed, all Viper Keys will be returned.

func (*StatusInfo) String

func (s *StatusInfo) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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