Documentation ¶
Overview ¶
Package glick provides a simple plug-in environment.
The central feature of glick is the Library which contains example types for the input and output of each API on the system. Each of these APIs can have a number of "actions" upon them, for example a file conversion API may have one action for each of the file formats to be convereted. Using the Run() method of glick.Library, a given API/Action combination runs the code in a function of Go type Plugin.
Although it is easy to create your own plugins, there are three types built-in: Remote Procedure Calls (RPC), simple URL fetch (URL) and OS commands (CMD). A number of sub-packages simplify the use of third-party libraries when providing further types of plugin.
The mapping of which plugin code to run occurs at three levels:
1) Intialisation and set-up code for the application will establish the glick.Library using glick.New(), then add API specifications using RegAPI(), it may also add the application's base plugins using RegPlugin().
2) The base set-up can be extended and overloaded using a JSON format configuration description (probaly held in a file) by calling the Config() method of glick.Library. This configuration process is extensible, using the AddConfigurator() method - see the glick/glpie or glick/glkit sub-pakages for examples.
3) Which plugin to use can also be set-up or overloaded at runtime within Run(). Each call to a plugin includes a Context (as described in https://blog.golang.org/context). This context can contain for example user details, which could be matched against a database to see if that user should be directed to one plugin for a given action, rather than another. It could also be used to wrap every plugin call by a particular user with some other code, for example to log or meter activity.
Example ¶
package main import ( "fmt" "time" "github.com/documize/glick" "golang.org/x/net/context" ) func main() { goDatePlugin := func(ctx context.Context, in interface{}) (interface{}, error) { return time.Now().String(), nil } runtimeRerouter := func(ctx context.Context, api, action string, handler glick.Plugin) (context.Context, glick.Plugin, error) { // if we hit a particular set of circumstances return the go version if ctx.Value("bingo") != nil && api == "timeNow" && action == "lookup" { return ctx, goDatePlugin, nil } // otherwise return what we we were planning to do anyway return ctx, handler, nil } lib, nerr := glick.New(runtimeRerouter) if nerr != nil { fmt.Println(nerr) return } timeNowAPIproto := "" if err := lib.RegAPI("timeNow", timeNowAPIproto, func() interface{} { return timeNowAPIproto }, time.Second); err != nil { fmt.Println(err) return } // the set-up version of the plugin, in Go if err := lib.RegPlugin("timeNow", "lookup", goDatePlugin, nil); err != nil { fmt.Println(err) return } ctx := context.Background() lookup := func() { if S, err := lib.Run(ctx, "timeNow", "lookup", ""); err != nil { fmt.Println(err) } else { fmt.Println(S) } } lookup() // should run the go version // now overload an os version of timeNow/lookup via a JSON config if err := lib.Configure([]byte(`[ {"Plugin":"OS-style-date","API":"timeNow","Actions":["lookup"],"Type":"CMD","Cmd":["date"]} ]`)); err != nil { fmt.Println(err) } lookup() // should run the os command 'date' and print the output // now set a specific context to be picked-up in runtimeRerouter ctx = context.WithValue(ctx, "bingo", "house") lookup() // should run the go version again after being re-routed }
Output:
Index ¶
- Variables
- func ConfigCmd(lib *Library) error
- func ConfigGetURL(lib *Library) error
- func ConfigRPC(lib *Library) error
- func IsText(t interface{}) bool
- func Port(configJSONpath, pluginServerName string) (string, error)
- func TextBytes(t interface{}) ([]byte, error)
- func TextConvert(b []byte, model interface{}) (interface{}, error)
- func TextReader(t interface{}) (io.Reader, error)
- type Config
- type Configurator
- type Library
- func (l *Library) Actions(api string) ([]string, error)
- func (l *Library) AddConfigurator(name string, cfg Configurator) error
- func (l *Library) Config(api, action string) *Config
- func (l *Library) Configure(b []byte) error
- func (l *Library) Disable(api string, actions []string)
- func (l *Library) KillSubProcs() error
- func (l *Library) ProtoPlugOut(api string) (ppo ProtoPlugOut, err error)
- func (l *Library) RegAPI(api string, inPrototype interface{}, outPlugProto ProtoPlugOut, ...) error
- func (l *Library) RegPlugin(api, action string, handler Plugin, cfg *Config) error
- func (l *Library) Run(ctx context.Context, api, action string, in interface{}) (out interface{}, err error)
- func (l *Library) StartLocalRPCservers(stdOut, stdErr io.Writer) error
- func (l *Library) Token(api, action string) string
- func (l *Library) ValidTypes() []string
- type Overloader
- type Plugin
- type ProtoPlugOut
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNilLib means the library pointer is nil. ErrNilLib = errors.New("nil library") // ErrNilAPI means an API value is nil. ErrNilAPI = errors.New("nil api") )
var ErrNotText = errors.New("interface value is not string or []byte, or pointer to string or []byte")
ErrNotText not a simple text value held in string or []byte, or a pointer to them.
var InsecureSkipVerifyTLS = false
InsecureSkipVerifyTLS should only be set to true when testing.
Functions ¶
func ConfigCmd ¶
ConfigCmd provides the Configurator for plugins that run operating system commands.
func ConfigGetURL ¶
ConfigGetURL provides the Configurator for the URL class of plugins that fetch the content of URLs.
func IsText ¶
func IsText(t interface{}) bool
IsText defines what can be a textual value, that is one of: string, *string, []byte or *[]byte.
func Port ¶
Port returns the first port number it comes across for a given Plugin name in a json config file, in the form: ":9999". TODO add tests for this code.
func TextBytes ¶
TextBytes returns a []byte when given a textual value that is one of: string, *string, []byte or *[]byte.
func TextConvert ¶
TextConvert takes a []byte value and returs a new textual value of the same type as the model, that is one of: string, *string, []byte or *[]byte.
func TextReader ¶
TextReader returns an io.Reader when given a textual value that is one of: string, *string, []byte or *[]byte.
Types ¶
type Config ¶
type Config struct { Plugin string // name of the plugin server, used to configure URL ports. API string // must already exist. Actions []string // these must be unique within the API. Token string // authorisation string to pass in the API, if it contains a Token field. Type string // the type of plugin, e.g. "RPC","URL","CMD"... Method string // the service method to use in the plugin, if relavent. Path string // path to the end-point for "RPC" or "URL". Cmd []string // command to run to start an image in "CMD", or to start a local "RPC" server. Comment string // a place to put comments about the entry. // bools at the end to make the structure smaller Disabled bool // disable the plugin(s) or plugin server by setting this to true. Gob bool // should the plugin use GOB encoding rather than JSON, if relavent. Static bool // only used by "URL" to signal a static address. }
Config defines a line in the JSON configuration file for a glick Libarary.
type Configurator ¶
Configurator is a type of function that allows plug-in fuctionality to the Config process.
type Library ¶
type Library struct {
// contains filtered or unexported fields
}
Library holds the registered API and plugin database.
func (*Library) AddConfigurator ¶
func (l *Library) AddConfigurator(name string, cfg Configurator) error
AddConfigurator adds a type of configuration to the library.
func (*Library) Config ¶
Config returns a pointer to the JSON Config struct for a given API and Action, or nil if no Config exists.
func (*Library) Configure ¶
Configure takes a JSON-encoded byte slice and configures the plugins for a library from it. NOTE: duplicate actions overload earlier versions.
func (*Library) KillSubProcs ¶
KillSubProcs created by StartLocalRPCservers() (or eventually maybe elsewhere).
func (*Library) ProtoPlugOut ¶
func (l *Library) ProtoPlugOut(api string) (ppo ProtoPlugOut, err error)
ProtoPlugOut provides the way to return a function to create the output for a plugin.
func (*Library) RegAPI ¶
func (l *Library) RegAPI(api string, inPrototype interface{}, outPlugProto ProtoPlugOut, timeout time.Duration) error
RegAPI allows registration of a named API. The in/out prototype defines the type that must be passed in and out. The timeout gives the maximum time that a Plugin using this API may take to execute.
func (*Library) RegPlugin ¶
RegPlugin registers a Plugger to use for this action on an api. Duplicate actions simply overload what is there.
func (*Library) Run ¶
func (l *Library) Run(ctx context.Context, api, action string, in interface{}) (out interface{}, err error)
Run a plugin for a given action on an API, passing data in/out. The library overloader function may decide from the context that a non-standard action should be run.
func (*Library) StartLocalRPCservers ¶
StartLocalRPCservers starts up local RPC server plugins. TODO add tests.
func (*Library) Token ¶
Token is a convenience function that returns the Token string for a given API and Action, if one exists.
func (*Library) ValidTypes ¶
ValidTypes returns all the valid plugin type names.
type Overloader ¶
type Overloader func(ctx context.Context, api, action string, handler Plugin) (context.Context, Plugin, error)
Overloader allows the standard system settings for an API to be overloaded, depending on the context passed in.
type Plugin ¶
Plugin type provides the type of the every plugin function, it has the same signature as Endpoint in "github.com/go-kit/kit".
func PluginCmd ¶
PluginCmd only works with an api with a simple Text/Text signature. it runs the given operating system command using the input string as stdin and putting stdout into the output string. At present, to limit stress on system resources, only one os command can run at a time via this plugin sub-system.
func PluginGetURL ¶
PluginGetURL fetches the content of a URL, which could be static or dynamic (passed in). It only works with an api with a simple Text/Text signature.
func PluginRPC ¶
func PluginRPC(useJSON bool, serviceMethod, endPoint string, ppo ProtoPlugOut) Plugin
PluginRPC returns a type which implements the Plugger interface for making an RPC. The return type of this class of plugin must be a pointer. The plugin creates a client per call to allow services to go up-and-down between calls.
type ProtoPlugOut ¶
type ProtoPlugOut func() interface{}
ProtoPlugOut provides a prototype for the output of a Plugger
Directories ¶
Path | Synopsis |
---|---|
Package glkit enables integration with gokit.io from the glick library.
|
Package glkit enables integration with gokit.io from the glick library. |
Package glpie exists to allow use of "github.com/natefinch/pie" (a toolkit for creating plugins for Go applications) from the glick package.
|
Package glpie exists to allow use of "github.com/natefinch/pie" (a toolkit for creating plugins for Go applications) from the glick package. |