kconfig

package
v0.0.0-...-895b022 Latest Latest
Warning

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

Go to latest
Published: Dec 13, 2024 License: BSD-3-Clause, BSD-3-Clause Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const (
	EncodeNone      EncodeAs = "string"    // The value is to be passed as is.
	EncodeFile               = "file"      // The value is to be stored in a file, and the path of the file passed to the flag.
	EncodeHex                = "hex"       // The value is to be hex encoded.
	EncodeBase64             = "base64"    // The value is to be base64 encoded.
	EncodeBase64Url          = "base64url" // The value is to be base64 encoded, using url encoding (avoids / and similar)

)

Variables

View Source
var YodaSays = "Do. Or do not. There is no try. And there is no config either."

What is this? With HTTP, it is incredibly difficult to reliably detect an error. With load balancers, and two requests in parallel, one can succeed, the other fail. Further, one can say "the file does not exist", because the configuration of one server is out of sync, while the other happily serves the file.

A reverse proxy can return a cached result, or an error message while happily returning a 200 Status OK. Or serve the wrong file. It's so sad.

The code in this library is extremely conservative: for any error whatsover, including 404s, it will retry fetching the config, in the hope that it was a transient failure.

However, if a web server returns a 404 with the YodaSays message followed by " On <current time>", the library will trust that the correct server was reached, and the config effectively does not exist. Curbing the time to complete.

It's a ugly hack. Likely unneccessary. But I couldn't resist the force, and I had to introduce it. Don't be on the dark side, don't remove this.

Functions

func BuildMap

func BuildMap(vars []Var, flagarg []kflags.FlagArg) map[string]interface{}

BuildMap creates a map to use for template expansion contain vars and flags.

func CacheFile

func CacheFile(path string) string

func CreateExecuteAction

func CreateExecuteAction(packagedir string, commanddir string, argv []string, vars []Var, mangler kflags.VarMangler, printer logger.Printer) (kflags.CommandAction, error)

func DefaultOptions

func DefaultOptions() *options

func EncodeFromFile

func EncodeFromFile(path string, encoding EncodeAs) (string, error)

func EncodeFromString

func EncodeFromString(cache cache.Store, retrieved string, encoding EncodeAs) (string, error)

func ExpandArgs

func ExpandArgs(argv []string, subs map[string]interface{}) ([]string, error)

ExpandArg takes a key:value map, and expands {{.key}} into an array of strings, using golang template syntax.

func FallbackFile

func FallbackFile(cs cache.Store, domain string) (string, error)

func PrepareEnv

func PrepareEnv(subs map[string]interface{}, mangler kflags.VarMangler) []string

ExpandArg takes a key:value map, and creates environment variables containging the key and value.

Types

type Callback

type Callback func(origin, value string, err error)

Callback is used to return the value of a parameter.

origin is a string identifying where the value is coming from. It can be a file name, an url, or... It is useful for debugging purposes, or to implement heuristics to determine the format of the value (example: is it json? yaml? let's hope there is an extension).

value is the retrieved value, it is only valid if err is nil. err indicates if an error happened during retrieval.

type Command

type Command struct {
	kflags.CommandDefinition `yaml:",inline"`

	Flag           []kflags.FlagDefinition
	Implementation *Implementation
}

type CommandFactory

type CommandFactory func(url, hash string) (string, *Manifest, error)

CommandFactory is a function capable of retrieving a command implementation.

type CommandRetriever

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

func NewCommandRetriever

func NewCommandRetriever(log logger.Logger, cache cache.Store, retrier *retry.Options, mods ...protocol.Modifier) *CommandRetriever

func (*CommandRetriever) Prepare

func (cr *CommandRetriever) Prepare(url, hash string) (string, error)

func (*CommandRetriever) PrepareHash

func (cr *CommandRetriever) PrepareHash(url, hash string) (string, error)

func (*CommandRetriever) PrepareURL

func (cr *CommandRetriever) PrepareURL(url string) (string, error)

func (*CommandRetriever) Retrieve

func (cr *CommandRetriever) Retrieve(url, hash string) (string, *Manifest, error)

type Config

type Config struct {
	Include   []string
	Namespace []Namespace
}

Goal of a Config is to specify a list of defaults to apply to all the flags in a namespace.

The Config data structure specifies:

a) A list of defaults for each namespace (Namespace)
b) A list of external config files to fallback to (Include)

When a flag is looked up:

1) First, the list of current Namespace is looked up. If a match is found, the default is set. 2) In order from last to first, all the includes are processed. The default of the first matching include is used.

func Parse

func Parse(name string, data []byte) (*Config, error)

Parse unmarshals a blob of bytes retrieved from a file or URL into a Config object.

type ConfigAugmenter

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

ConfigAugmenter is an Augmenter filling flags and commands based on the content of a configuration file.

The format of the configuration file is defined in the interface.go file, and represented by the Config struct.

Given that a config file can recursively include other configs, a ConfigAugmenter may internally parse other config files, and recursively create other ConfigAugmenter objects.

func NewConfigAugmenter

func NewConfigAugmenter(cs cache.Store, config *Config, mods ...Modifier) (*ConfigAugmenter, error)

func NewConfigAugmenterFromDNS

func NewConfigAugmenterFromDNS(cs cache.Store, domain string, binary string, mods ...Modifier) (*ConfigAugmenter, error)

func NewConfigAugmenterFromURL

func NewConfigAugmenterFromURL(cs cache.Store, url string, mods ...Modifier) (*ConfigAugmenter, error)

func (*ConfigAugmenter) Done

func (cr *ConfigAugmenter) Done() error

Done completes the augmentation process.

It recursively invokes the Done method of the augmenters that have been **used**. It does NOT wait for augmenters that have NOT been used, even if configured.

func (*ConfigAugmenter) VisitCommand

func (cr *ConfigAugmenter) VisitCommand(namespace string, command kflags.Command) (bool, error)

func (*ConfigAugmenter) VisitFlag

func (cr *ConfigAugmenter) VisitFlag(ns string, flag kflags.Flag) (bool, error)

type Creator

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

Creator is an object capable of creating and sharing retrievers.

Creator ensures that for a given parameter or url, only one retriever is instantiated, and the result cached for the lifetime of the Creator.

This allows a complex configuration file re-using the same parameters over and over to have a very little impact in terms of latency, reliability, and bandwidth.

func NewCreator

func NewCreator(log logger.Logger, cache cache.Store, downloader *downloader.Downloader, mods ...downloader.Modifier) *Creator

func (*Creator) Create

func (f *Creator) Create(base *url.URL, param *Parameter) (Retriever, error)

Create creates the Retriever for a specific parameter.

Create validates some of the parameter values, to ensure the validity of the request, and based on the type of request, returns the correct Retriever.

The returned retrieved is either newly created (if the value requested was never seen before) or returns an exisitng one (if the same value was requested by another parameter).

type EncodeAs

type EncodeAs string

type Flags

type Flags struct {
	Downloader     *downloader.Flags
	DNS            *remote.DNSFlags
	RecursionLimit int
}

func DefaultFlags

func DefaultFlags() *Flags

func (*Flags) Register

func (fl *Flags) Register(set kflags.FlagSet, prefix string) *Flags

type Implementation

type Implementation struct {
	// Having a Package results in a .tar.gz being downloaded from the specified URL,
	// and in the Manifest contained therein to be loaded.
	Package *Package
	Local   []string
	System  []string

	// Variables to pass to the Local and System commands.
	Var []Var
}

type InlineRetriever

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

func NewInlineRetriever

func NewInlineRetriever(cache cache.Store, param *Parameter) *InlineRetriever

func (*InlineRetriever) Retrieve

func (ir *InlineRetriever) Retrieve(callback Callback)

type Manifest

type Manifest struct {
	Command []Command
}

type Modifier

type Modifier func(*options) error

func FromFlags

func FromFlags(fl *Flags) Modifier

func WithBaseURL

func WithBaseURL(url string) Modifier

func WithCommandFactory

func WithCommandFactory(c CommandFactory) Modifier

func WithDNSOptions

func WithDNSOptions(mods ...remote.DNSModifier) Modifier

func WithDownloader

func WithDownloader(dl *downloader.Downloader) Modifier

func WithDownloaderOptions

func WithDownloaderOptions(mods ...downloader.Modifier) Modifier

func WithGetOptions

func WithGetOptions(mods ...downloader.Modifier) Modifier

func WithLogger

func WithLogger(l logger.Logger) Modifier

func WithMangler

func WithMangler(mangler kflags.VarMangler) Modifier

func WithOptions

func WithOptions(tocopy *options) Modifier

func WithParamFactory

func WithParamFactory(c ParamFactory) Modifier

func WithRecursionLimit

func WithRecursionLimit(recursionLimit int) Modifier

func WithSeenStack

func WithSeenStack(bl *SeenStack) Modifier

type Modifiers

type Modifiers []Modifier

func (Modifiers) Apply

func (mods Modifiers) Apply(o *options)

type Namespace

type Namespace struct {
	// If empty, it is assumed to be the name of the application.
	// Otherwise, it is a path using "." to separate subcommands.
	Name    string
	Hidden  bool
	Default []Parameter
	Command []Command
}

type NamespaceAugmenter

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

func NewNamespaceAugmenter

func NewNamespaceAugmenter(base *url.URL, namespaces []Namespace, log logger.Logger, mangler kflags.VarMangler, cf CommandFactory, pf ParamFactory) (*NamespaceAugmenter, error)

func (*NamespaceAugmenter) Done

func (c *NamespaceAugmenter) Done() error

func (*NamespaceAugmenter) VisitCommand

func (c *NamespaceAugmenter) VisitCommand(namespace string, command kflags.Command) (found bool, err error)

VisitCommand implements the VisitCommand interface in kflags.Augmenter.

There are a few nuisances about VisitCommand, and ensuring it always runs fast without blocking.

For example:

Let's say that we have a "docker" command added by config, with "fpga" and "dev" sub commands. The "fpga" and "dev" subcommands are packages downloaded.

Now, when VisitCommand is called as...

VisitCommand("enkit") for `enkit --help`

  • --help should show the availability of a docker command, complete with description.
  • ideally, it should not require the download of the "fpga" and "dev" commands.
  • How? Config expanding the "enkit" namespace by adding the "docker" command, defined directly in the config file.

VisitCommand("enkit.docker") for `enkit docker --help`

  • --help should show the availability of a "dev" and "fpga" containers, complete with description. Further, the syntax should allow for specifying a version / tag.
  • How? Config expanding the "enkit.docker" namespace, adds the ... "dev" and "fpga" commands. Ideally, without downloading them. Just based on the config file, creates the command, sets an implementation, configures some flags.

VisitCommand("enkit.docker.dev") for `enkit docker dev --help`

  • --help should show the availability of run, login and upgrade.
  • How? dev has an implementation. It is downloaded and waited for. The inner manifest file is parsed, defining extra commands and flags.

VisitCommand("enkit.docker.dev") for `enkit docker dev:latest --help`

  • --help should show the availability of run, login, and upgrade, with their flags.
  • How? dev has an implementation.

func (*NamespaceAugmenter) VisitFlag

func (c *NamespaceAugmenter) VisitFlag(namespace string, flag kflags.Flag) (bool, error)

type Package

type Package struct {
	URL  string
	Hash string
}

type ParamFactory

type ParamFactory func(base *url.URL, param *Parameter) (Retriever, error)

ParamFactory is a function capable of creating a Retriever (or returning an error...) for a given config Parameter.

If a parameter uses a relative URL, it will be considered relative to base.

type Parameter

type Parameter struct {
	Name  string // What is the name of the parameter?
	Value string // Value is the string value of the parameter.

	Source   SourceFrom // Where to get the value from.
	Encoding EncodeAs   // How to encode the value.

	Hash string // Optional: hash of the value, uesful only when SourceURL is used.
}

type Retriever

type Retriever interface {
	Retrieve(Callback)
}

Retriever is an object capable of retrieving the value of a parameter.

Generally, a retriever is created when the configuration is parsed, to, for example, download the value from an internal config store.

Retrievers, however, will only start fetching the value when it is actually needed, when the Retrieve() method is invoked.

Generally, you should not create a retriever directly, but through the Creator object below.

type SeenStack

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

SeenStack is an object used to prevent inclusion and redirect loops.

It is meant to keep track of all previously seen URLs, the nesting level, and return an error if any of the URLs is encountered again.

SeenStack is thread safe: once created, all its methods can safely be invoked from any thread.

func NewSeenStack

func NewSeenStack() *SeenStack

NewSeenStack creates a new SeenStack.

func (*SeenStack) Add

func (bl *SeenStack) Add(url string) (int, error)

Add adds a new URL to the SeenStack.

Always returns the nesting levels, how many URLs were seen already.

If the url added is known, and was already visited, the function also returns a fmt.Errorf() with a helpful message to help debug the problem.

func (*SeenStack) Stack

func (bl *SeenStack) Stack() []string

Stack returns the list of URLs already visited.

type SourceFrom

type SourceFrom string
const (
	SourceInline SourceFrom = "inline" // The value represents a string to pass to the env or flag after encoding.
	SourceURL               = "url"    // The value represents an http / https url to retrieve, encode, and pass as env or flag.

)

type URLRetriever

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

func NewURLRetriever

func NewURLRetriever(log logger.Logger, cache cache.Store, dl *downloader.Downloader, url *url.URL, param *Parameter, mods ...downloader.Modifier) *URLRetriever

func (*URLRetriever) Call

func (p *URLRetriever) Call(callback Callback) bool

Call will invoke the callback with the retrieved value.

Returns true if nothing has to be done by the caller (eg, the call has been performed, or the request is pending the fetching of the data).

Returns false if the caller has to provide the value with Set for the callback to be invoked.

func (*URLRetriever) Deliver

func (p *URLRetriever) Deliver(origin, value string, err error)

func (*URLRetriever) DeliverError

func (p *URLRetriever) DeliverError(err error)

func (*URLRetriever) Retrieve

func (p *URLRetriever) Retrieve(callback Callback)

func (*URLRetriever) RetrieveByHash

func (p *URLRetriever) RetrieveByHash() error

Retrieve by hash retrieves a parameter from a URL with a hash.

It does not use an HTTP cache, Last-Modifier, or If-Modified-Since sorcery, as the Hash already identifies the file uniquely. Eg, if we have a file by that hash, no need to fetch it. If we don't, then we must fetch it.

func (*URLRetriever) RetrieveByPath

func (p *URLRetriever) RetrieveByPath()

type Var

type Var struct {
	Key, Value string
}

Jump to

Keyboard shortcuts

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