Documentation
¶
Overview ¶
Package plugins expands on the standard library "plugin" package to provide the basis for building modular, plugin-based applications.
This package implements both Plugin and PluginAgent functionality for both Server and Client type applications.
Plugins ¶
A "Plugin" or module within this package refers to a set of Go packages which implements a public interface matching the basic common interface described in the "PluginAPI" struct. This provides all of the necessary functionality to work with a plugin except for starting it. Each of the separate "ClientPluginAPI" and "ServerPluginAPI" structs provide extensions to the basic interface to include an "Init()" method. This Init() method is the standard way to start a plugin.
The methods of the PluginAPI are expected to function in a common manner across any type of plugin, with only the Init() method being customized to specific plugin types.
Server Plugins ¶
Server plugins are primarily a mechanism to allow building up a Server-side application with the easy-tls/server package, and generating the routing tree dynamically. The Init() function returns an array of SimpleHandler objects, which provide all of the necessary information to be registered with the incorporated HTTP Router. As such, the Init function must perform any internal initialization, and spawn any concurrent go-routines which may need to keep running after Init() returns, while also preparing the array of handlers to actually be returned.
Once Init() returns for a ServerPlugin, only go-routines spawned during Init will continue to execute, with any incoming requests being passed in to the specified handler.
Client Plugins ¶
Client plugins are substantially different from server plugins in structure. These are best modelled as "stand-alone" applications, with the Init() call equivalent to calling their "main()" function. Arguments can be provided, but must be entirely parsed from the interface array within Init(). Init() is expected to return after "forking" off a go-routine to perform the main body of the plugin, typically a main loop.
Plugin Agents ¶
In addition to plugins and the necessary functionality to work with them, this package includes Agents to oversee and work with sets of plugins in a simple fashion. These handle the process of loading plugins, extracting the functions forming their public interface, starting, stopping, and logging the Plugins. When building a modular application with this library, the Agents are expected to be the primary driver of the modular functionality.
The only real difference between the Server and Client agents are the Init() functions they look for.
Index ¶
- Constants
- Variables
- func Accepts(Is, AcceptsMin, AcceptsMax SemanticVersion) bool
- type Agent
- func (A *Agent) AddCommonArguments(args ...interface{})
- func (A *Agent) Close() error
- func (A *Agent) Done() chan struct{}
- func (A *Agent) GetByName(Substring string) (Module, error)
- func (A *Agent) Logger() *log.Logger
- func (A *Agent) Modules() []Module
- func (A *Agent) NewGenericModule(Filename string) *GenericPlugin
- func (A *Agent) SendCommands(Args ...string)
- func (A *Agent) SetLogger(l *log.Logger)
- func (A *Agent) StartAll() error
- func (A *Agent) StopAll() error
- func (A *Agent) Wait()
- type ClientAgent
- type ClientInitFunc
- type ClientPlugin
- type ContextManager
- type GenericPlugin
- func (p *GenericPlugin) AddArguments(args ...interface{})
- func (p *GenericPlugin) Done() <-chan struct{}
- func (p *GenericPlugin) GetVersion() (*SemanticVersion, error)
- func (p *GenericPlugin) Load() error
- func (p *GenericPlugin) Name() string
- func (p *GenericPlugin) ReadStatus() error
- func (p *GenericPlugin) Reload() error
- func (p *GenericPlugin) Start(Args ...interface{}) error
- func (p *GenericPlugin) State() PluginState
- func (p *GenericPlugin) Stop() error
- func (p *GenericPlugin) Uptime() time.Duration
- type InitFunc
- type Module
- type NameFunc
- type PluginState
- type PluginStatus
- type SemanticVersion
- type ServerAgent
- type ServerInitHandlersFunc
- type ServerInitSubrouterFunc
- type ServerPlugin
- type StatusFunc
- type StatusWriter
- func (W *StatusWriter) Channel() (<-chan PluginStatus, error)
- func (W *StatusWriter) Close(err error)
- func (W *StatusWriter) Fatalf(Message string, Err error, args ...interface{})
- func (W *StatusWriter) Out(S PluginStatus)
- func (W *StatusWriter) Printf(Message string, Err error, args ...interface{})
- type StopFunc
- type VersionFunc
Constants ¶
const ( URLStartHandler string = "/start/{Name}" URLRestartHandler string = "/restart/{Name}" URLReloadHandler string = "/reload/{Name}" URLVersionHandler string = "/version/{Name}" URLStopHandler string = "/stop/{Name}" URLStateHandler string = "/state/{Name}" URLListHandler string = "/list" URLActiveHandler string = "/active" URLHelpHandler string = "/" )
URL Definitions, to easily share between client and server sides of the channel
const (
HeaderArgumentKey string = "Agent-Arguments"
)
HTTP Header Key definition, to easily share between sender and receiver
Variables ¶
var ClientFrameworkVersion = SemanticVersion{
MajorRelease: 1,
MinorRelease: 4,
Build: 1,
}
ClientFrameworkVersion represents the current Semantic Version of the Client-side Plugin agent framework
var ErrNoContext error = errors.New("context manager error: No CancelFunc for key")
ErrNoContext indicates there is no context for the provided key.
var ( // ErrNoModule indicates that no module exists for a given search ErrNoModule = errors.New("plugin agent error: No module found for key") )
var ( // ErrOtherServerActive indicates that the server cannot activate, since there is already a server // active on the bind address it uses. ErrOtherServerActive error = errors.New("plugin command server error: Failed to initialize, bind address already active") )
var GenericFrameworkVersion = SemanticVersion{
MajorRelease: 1,
MinorRelease: 4,
Build: 1,
}
GenericFrameworkVersion represents the current Semantic Version of the Generic Plugin agent framework
var ServerFrameworkVersion = SemanticVersion{
MajorRelease: 1,
MinorRelease: 4,
Build: 1,
}
ServerFrameworkVersion represents the current Semantic Version of the Server-side Plugin agent framework
Functions ¶
func Accepts ¶
func Accepts(Is, AcceptsMin, AcceptsMax SemanticVersion) bool
Accepts determines if a given version is accepted for a set of minimum and maximum acceptable versions
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent represets the Generic Plugin manager which oversees and acts on the loadable plugins. For specific Client and Server plugin managers, this must be extended with either ClientAgent or ServerAgent objects.
func (*Agent) AddCommonArguments ¶
func (A *Agent) AddCommonArguments(args ...interface{})
AddCommonArguments will add a set of arguments to all currently loaded plugins
func (*Agent) Close ¶
Close will close down an agent, stopping all plugins and releasing all resources
func (*Agent) Done ¶
func (A *Agent) Done() chan struct{}
Done returns a channel which strobes when the agent is safely closed.
func (*Agent) GetByName ¶
GetByName will attempt to retrieve a module with a given name substring from the agent to be able to manipulate it.
func (*Agent) Modules ¶
Modules will return the set of known modules as an array in name sorted order, regardless of the underlying formatting.
func (*Agent) NewGenericModule ¶
func (A *Agent) NewGenericModule(Filename string) *GenericPlugin
NewGenericModule will return a new GenericPlugin, which satisfies most, but not all of the Module interface. This GenericPlugin should be embedded into a greater object which fills in the final missing members of the Module interface.
func (*Agent) SendCommands ¶
SendCommands is the top-level function to send a command to the command-server of another plugin agent, to cause it to perform actions on the set of plugins it has. These actions exactly correspond to the set of methods within the Module interface.
A given command is composed of 2 strings:
Action Name
The receiving handler will attempt to perform the given action on the plugin who matches the Name. This can be just a prefix of the full name. The snippet provided will always match in lexicographic order, so if one module is a prefix of another, and a sub-prefix is given, the shortest name will match first.
type ClientAgent ¶
type ClientAgent struct { *Agent // contains filtered or unexported fields }
ClientAgent represents a plugin manager for Server-type plugins
func NewClientAgent ¶
func NewClientAgent(ModuleFolder string, Client *client.SimpleClient) (A *ClientAgent, err error)
NewClientAgent will fully create and initialize a new ClientAgent. This will NOT start any plugins, but will put the Agent into a state where all available plugins could be started.
type ClientInitFunc ¶
type ClientInitFunc = func(*client.SimpleClient, ...interface{}) error
ClientInitFunc is the defined type of the Init function exported by compliant plugins to spawn a new Client plugin.
type ClientPlugin ¶
type ClientPlugin struct { GenericPlugin // contains filtered or unexported fields }
ClientPlugin extends GenericPlugin to satisfy the Module interface with Init() functions specific to client-type plugins.
func (*ClientPlugin) Reload ¶
func (p *ClientPlugin) Reload() error
Reload will fully reload a module. This will stop a running module, and load the symbols fresh from disk.
func (*ClientPlugin) Start ¶
func (p *ClientPlugin) Start(Args ...interface{}) error
Start will start the module, performing any initialization and putting it into a state where the logic included by the plugin can be used.
type ContextManager ¶
ContextManager represents an abstract object to help manage the contexts held/opened by a given module. This object allows for the Stop() function to properly and safely Cancel the contexts to allow the module to shut down safely.
func NewContextManager ¶
func NewContextManager() *ContextManager
NewContextManager will initialize a new ContextManager, making it ready to use.
func (*ContextManager) Cancel ¶
func (C *ContextManager) Cancel(Key int64) error
Cancel will call the CancelFunc (if it exists) for the given Key, removing the stored function from the manager once the cancel completes.
func (*ContextManager) Close ¶
func (C *ContextManager) Close()
Close will close a ContextManager, cancelling all contexts which have not been removed from the manager yet.
func (*ContextManager) GetCancel ¶
func (C *ContextManager) GetCancel(Key int64) (context.CancelFunc, error)
GetCancel will return the CancelFunc for a given Key, allowing the caller to act on it.
func (*ContextManager) NewContext ¶
func (C *ContextManager) NewContext() (ctx context.Context, x int64)
NewContext creates and new context.WithCancel() context to be used by the caller. This function saves the CancelFunc for the generated context, returning and int64 token which can be used to manipulate the CancelFunc later.
This returned context should be extended to any other type of context as necessary, such as WithDeadline() or WithValue(). This simply ensures the parent context is cancellable to prevent undesirable waits when stopping plugins.
func (*ContextManager) RemoveContext ¶
func (C *ContextManager) RemoveContext(Key int64)
RemoveContext will remove the CancelFunc for a given key, indicating that the related context has successfully finished whatever task it was related to and no longer needs to be able to be cancelled externally.
Standard operation involves calls like:
ctx, Key := Manager.NewContext() defer Manager.RemoveContext(Key) // functionality here to use ctx.
Or:
ctx, Key := Manager.NewContext() // Use ctx Manager.RemoveContext(Key)
type GenericPlugin ¶
type GenericPlugin struct {
// contains filtered or unexported fields
}
GenericPlugin implements a basic version of the Module interface, specifically the set of parameters and methods which are generic and common across either client, server, or other modules.
func (*GenericPlugin) AddArguments ¶
func (p *GenericPlugin) AddArguments(args ...interface{})
AddArguments will append the given arguments to the set of arguments to pass in to the plugin
func (*GenericPlugin) Done ¶
func (p *GenericPlugin) Done() <-chan struct{}
Done will return a channel that fires once then closes to indicate that a plugin is finished.
func (*GenericPlugin) GetVersion ¶
func (p *GenericPlugin) GetVersion() (*SemanticVersion, error)
GetVersion will return the version information of the plugin, as reported in the canonical name,
func (*GenericPlugin) Load ¶
func (p *GenericPlugin) Load() error
Load implements the most generic Load functionality for a generic plugin. This will typically be overloaded/superceded by the more specific implementation of the Module interface.
func (*GenericPlugin) Name ¶
func (p *GenericPlugin) Name() string
Name satisfies the Name() component of the Module interface by calling the generic Name() function exported by the plugins
func (*GenericPlugin) ReadStatus ¶
func (p *GenericPlugin) ReadStatus() error
ReadStatus will spawn a go-routine to read messages off the Status() channel from the plugin until it is closed.
func (*GenericPlugin) Reload ¶
func (p *GenericPlugin) Reload() error
Reload implements the most generic Reload functionality for a generic plugin. This will typically be overloaded/superceded by the more specific implementation of the Module interface.
func (*GenericPlugin) Start ¶
func (p *GenericPlugin) Start(Args ...interface{}) error
Start implements the most generic Start functionality for a generic plugin. This will typically be overloaded/superceded by the more specific implementation of the Module interface.
func (*GenericPlugin) State ¶
func (p *GenericPlugin) State() PluginState
State exposes the internal state variable, so it can be queried.
func (*GenericPlugin) Stop ¶
func (p *GenericPlugin) Stop() error
Stop implements the Stop method of the Module interface. This will stop the logic of the plugin according to the exported Stop() function, and will wait for ALL status messages to be written out before returning any errors which occurred during shutdown
func (*GenericPlugin) Uptime ¶
func (p *GenericPlugin) Uptime() time.Duration
Uptime will return how long a module has been active for
type InitFunc ¶
type InitFunc = func(...interface{}) error
InitFunc is the defined type of the most generic Init function exported by generic plugins. This does not need to be exported, as long as SOME Init() function is exported, and whatever implementation of the Module interface is used, properly extracts this symbol.
type Module ¶
type Module interface { Start(...interface{}) error GetVersion() (*SemanticVersion, error) Uptime() time.Duration Reload() error Stop() error State() PluginState Load() error Name() string ReadStatus() error Done() <-chan struct{} AddArguments(...interface{}) }
Module is the interface which must be satisfied by any plugins intended to be managed by this package. This is distinct from the API Contract the module must satisfy, which refers to the set of functions and signatures the module must export. This interface refers to how the Plugin Agent will communicate with a module, regardless of what these actual exported signatures are.
type NameFunc ¶
type NameFunc = func() string
NameFunc is the defined type of the Name function exported by all compliant plugins.
type PluginState ¶
type PluginState int
PluginState represents the current state of a plugin
func (PluginState) String ¶
func (S PluginState) String() string
type PluginStatus ¶
type PluginStatus struct {
// contains filtered or unexported fields
}
PluginStatus represents a single status message from a given EasyTLS-compliant plugin.
func NewPluginStatus ¶
func NewPluginStatus(Message string, Err error, Fatal bool) PluginStatus
NewPluginStatus creates and returns a new status message, able to be sent via Statuswriter
func (*PluginStatus) Error ¶
func (S *PluginStatus) Error() string
func (*PluginStatus) String ¶
func (S *PluginStatus) String() string
type SemanticVersion ¶
SemanticVersion represents a useable semantic version number. This can be used to assert compatability between plugins, agents, and frameworks.
func ParseVersion ¶
func ParseVersion(v string) (*SemanticVersion, error)
ParseVersion allows for a SemanticVersion to be recovered from its string representation.
func (*SemanticVersion) String ¶
func (v *SemanticVersion) String() string
type ServerAgent ¶
type ServerAgent struct { *Agent // contains filtered or unexported fields }
ServerAgent represents a plugin manager for Server-type plugins
func NewServerAgent ¶
func NewServerAgent(ModuleFolder, URLRoot string, Server *server.SimpleServer) (A *ServerAgent, err error)
NewServerAgent will fully create and initialize a new ServerAgent. This will NOT start any plugins, but will put the Agent into a state where all available plugins could be started.
type ServerInitHandlersFunc ¶
type ServerInitHandlersFunc = func(...interface{}) ([]server.SimpleHandler, error)
ServerInitHandlersFunc is the defined type of the Init function exported by compliant plugins to register a set of routes with the default router.
type ServerInitSubrouterFunc ¶
type ServerInitSubrouterFunc = func(...interface{}) ([]server.SimpleHandler, string, error)
ServerInitSubrouterFunc is the defined type of the Init function exported by compliant plugins to register a set of routes with a dedicated SubRouter with the returned string acting as the URL PathPrefix.
type ServerPlugin ¶
type ServerPlugin struct { GenericPlugin // contains filtered or unexported fields }
ServerPlugin extends GenericPlugin to satisfy the Module interface with Init() functions specific to server-type plugins.
func (*ServerPlugin) Reload ¶
func (p *ServerPlugin) Reload() error
Reload will fully reload a module. This will stop a running module, and load the symbols fresh from disk.
func (*ServerPlugin) Start ¶
func (p *ServerPlugin) Start(Args ...interface{}) error
Start will start the module, performing any initialization and putting it into a state where the logic included by the plugin can be used.
type StatusFunc ¶
type StatusFunc = func() (<-chan PluginStatus, error)
StatusFunc is the defined type of the Status function exported by all compliant plugins.
type StatusWriter ¶
type StatusWriter struct {
// contains filtered or unexported fields
}
StatusWriter is the encapsulation of how a plugin writes status messages out to the world.
func OpenStatusWriter ¶
func OpenStatusWriter(Length int, Name string) *StatusWriter
OpenStatusWriter will open a new StatusWriter for a given plugin.
func (*StatusWriter) Channel ¶
func (W *StatusWriter) Channel() (<-chan PluginStatus, error)
Channel will return the internal channel used by the plugin, to export it to the world
func (*StatusWriter) Close ¶
func (W *StatusWriter) Close(err error)
Close will safely close and lock the channel, preventing all other access.
func (*StatusWriter) Fatalf ¶
func (W *StatusWriter) Fatalf(Message string, Err error, args ...interface{})
Fatalf will format and print out a status message using the given Message fmt string and optional error. This will tell the framework to hard stop the plugin.
func (*StatusWriter) Out ¶
func (W *StatusWriter) Out(S PluginStatus)
Out allows sending a pre-formatted status message out
func (*StatusWriter) Printf ¶
func (W *StatusWriter) Printf(Message string, Err error, args ...interface{})
Printf will format and print out a status message using the given Message fmt string and optional error.
type StopFunc ¶
type StopFunc = func() error
StopFunc is the defined type of the Stop function exported by all compliant plugins.
type VersionFunc ¶
type VersionFunc = func(SemanticVersion) error
VersionFunc is the defined type of the Version function exported by all compliant plugins.