plugins

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: May 6, 2021 License: MIT Imports: 25 Imported by: 4

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

View Source
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

View Source
const (
	HeaderArgumentKey string = "Agent-Arguments"
)

HTTP Header Key definition, to easily share between sender and receiver

Variables

View Source
var ClientFrameworkVersion = SemanticVersion{
	MajorRelease: 1,
	MinorRelease: 4,
	Build:        1,
}

ClientFrameworkVersion represents the current Semantic Version of the Client-side Plugin agent framework

View Source
var ErrNoContext error = errors.New("context manager error: No CancelFunc for key")

ErrNoContext indicates there is no context for the provided key.

View Source
var (
	// ErrNoModule indicates that no module exists for a given search
	ErrNoModule = errors.New("plugin agent error: No module found for key")
)
View Source
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")
)
View Source
var GenericFrameworkVersion = SemanticVersion{
	MajorRelease: 1,
	MinorRelease: 4,
	Build:        1,
}

GenericFrameworkVersion represents the current Semantic Version of the Generic Plugin agent framework

View Source
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 NewAgent

func NewAgent(ModuleFolder string, logger *log.Logger) (*Agent, error)

NewAgent will create and return a new generic plugin agent.

func (*Agent) AddCommonArguments

func (A *Agent) AddCommonArguments(args ...interface{})

AddCommonArguments will add a set of arguments to all currently loaded plugins

func (*Agent) Close

func (A *Agent) Close() error

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

func (A *Agent) GetByName(Substring string) (Module, error)

GetByName will attempt to retrieve a module with a given name substring from the agent to be able to manipulate it.

func (*Agent) Logger

func (A *Agent) Logger() *log.Logger

Logger returns the logger used by an Agent

func (*Agent) Modules

func (A *Agent) Modules() []Module

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

func (A *Agent) SendCommands(Args ...string)

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.

func (*Agent) SetLogger

func (A *Agent) SetLogger(l *log.Logger)

SetLogger will set the internal logger of the Agent to l

func (*Agent) StartAll

func (A *Agent) StartAll() error

StartAll will run Start() for all of the included modules of the agent.

func (*Agent) StopAll

func (A *Agent) StopAll() error

StopAll will run Stop() for all of the included modules of the agent.

func (*Agent) Wait

func (A *Agent) Wait()

Wait will wait for all of the included modules to signal they are done before returning.

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) Load

func (p *ClientPlugin) Load() error

Load the symbols of the module

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

type ContextManager struct {
	*sync.Mutex
	// contains filtered or unexported fields
}

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

type SemanticVersion struct {
	MajorRelease int
	MinorRelease int
	Build        int
}

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) Load

func (p *ServerPlugin) Load() error

Load the symbols of the module

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.

Jump to

Keyboard shortcuts

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