Documentation ¶
Index ¶
- Constants
- Variables
- func BuildMap(vars []Var, flagarg []kflags.FlagArg) map[string]interface{}
- func CacheFile(path string) string
- func CreateExecuteAction(packagedir string, commanddir string, argv []string, vars []Var, ...) (kflags.CommandAction, error)
- func DefaultOptions() *options
- func EncodeFromFile(path string, encoding EncodeAs) (string, error)
- func EncodeFromString(cache cache.Store, retrieved string, encoding EncodeAs) (string, error)
- func ExpandArgs(argv []string, subs map[string]interface{}) ([]string, error)
- func FallbackFile(cs cache.Store, domain string) (string, error)
- func PrepareEnv(subs map[string]interface{}, mangler kflags.VarMangler) []string
- type Callback
- type Command
- type CommandFactory
- type CommandRetriever
- type Config
- type ConfigAugmenter
- func NewConfigAugmenter(cs cache.Store, config *Config, mods ...Modifier) (*ConfigAugmenter, error)
- func NewConfigAugmenterFromDNS(cs cache.Store, domain string, binary string, mods ...Modifier) (*ConfigAugmenter, error)
- func NewConfigAugmenterFromURL(cs cache.Store, url string, mods ...Modifier) (*ConfigAugmenter, error)
- type Creator
- type EncodeAs
- type Flags
- type Implementation
- type InlineRetriever
- type Manifest
- type Modifier
- func FromFlags(fl *Flags) Modifier
- func WithBaseURL(url string) Modifier
- func WithCommandFactory(c CommandFactory) Modifier
- func WithDNSOptions(mods ...remote.DNSModifier) Modifier
- func WithDownloader(dl *downloader.Downloader) Modifier
- func WithDownloaderOptions(mods ...downloader.Modifier) Modifier
- func WithGetOptions(mods ...downloader.Modifier) Modifier
- func WithLogger(l logger.Logger) Modifier
- func WithMangler(mangler kflags.VarMangler) Modifier
- func WithOptions(tocopy *options) Modifier
- func WithParamFactory(c ParamFactory) Modifier
- func WithRecursionLimit(recursionLimit int) Modifier
- func WithSeenStack(bl *SeenStack) Modifier
- type Modifiers
- type Namespace
- type NamespaceAugmenter
- type Package
- type ParamFactory
- type Parameter
- type Retriever
- type SeenStack
- type SourceFrom
- type URLRetriever
- type Var
Constants ¶
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 ¶
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 CreateExecuteAction ¶
func DefaultOptions ¶
func DefaultOptions() *options
func EncodeFromString ¶
func ExpandArgs ¶
ExpandArg takes a key:value map, and expands {{.key}} into an array of strings, using golang template syntax.
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 ¶
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 ¶
CommandFactory is a function capable of retrieving a command implementation.
type CommandRetriever ¶
type CommandRetriever struct {
// contains filtered or unexported fields
}
func NewCommandRetriever ¶
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)
type Config ¶
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.
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 (*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 ¶
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 ¶
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 Flags ¶
type Flags struct { Downloader *downloader.Flags DNS *remote.DNSFlags RecursionLimit int }
func DefaultFlags ¶
func DefaultFlags() *Flags
type Implementation ¶
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 Modifier ¶
type Modifier func(*options) error
func WithBaseURL ¶
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 WithMangler ¶
func WithMangler(mangler kflags.VarMangler) Modifier
func WithOptions ¶
func WithOptions(tocopy *options) Modifier
func WithParamFactory ¶
func WithParamFactory(c ParamFactory) Modifier
func WithRecursionLimit ¶
func WithSeenStack ¶
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.
type ParamFactory ¶
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.
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()