Documentation ¶
Overview ¶
Package plugin is the container for all things plugins. The top level package defines the interface for plugins. A plugin must, at the very least, provide an implementation of plugin.Interface. Then, that plugin is run by providing a main function that runs the plugin using the RunPlugin() function defined in "github.com/zostay/zedpm/plugin/metal".
From there, the plugin may:
* Define task implementations via the Implements, Prepare, Cancel, and Complete Prepare methods of the plugin.Interface.
* Define goals via the Goal method.
Plugins may be written in other languages than Golang. To do that, the plugin will need to implement the plugin interface defined by "github.com/hashicorp/go-plugin" to handle the startup of a gRPC server and then printing details regarding that gRPC server on stdout. The gRPC server implemented must implement the interface defined in the TaskExecution service found in task-interface.proto.
Index ¶
- Variables
- func ApplyChanges(ctx context.Context, changes map[string]string)
- func AtomicProperties(ctx context.Context, atomicOp func(storage.KV))
- func ForCleanup(ctx context.Context, newCleaner SimpleTask)
- func Get(ctx context.Context, key string) any
- func GetBool(ctx context.Context, key string) bool
- func GetDuration(ctx context.Context, key string) time.Duration
- func GetFloat64(ctx context.Context, key string) float64
- func GetInt(ctx context.Context, key string) int
- func GetInt32(ctx context.Context, key string) int32
- func GetInt64(ctx context.Context, key string) int64
- func GetIntSlice(ctx context.Context, key string) []int
- func GetString(ctx context.Context, key string) string
- func GetStringMap(ctx context.Context, key string) map[string]any
- func GetStringMapString(ctx context.Context, key string) map[string]string
- func GetStringMapStringSlice(ctx context.Context, key string) map[string][]string
- func GetStringSlice(ctx context.Context, key string) []string
- func GetTime(ctx context.Context, key string) time.Time
- func GetUint(ctx context.Context, key string) uint
- func GetUint16(ctx context.Context, key string) uint16
- func GetUint32(ctx context.Context, key string) uint32
- func GetUint64(ctx context.Context, key string) uint64
- func InitializeContext(ctx context.Context, pctx *Context) context.Context
- func IsSet(ctx context.Context, key string) bool
- func KV(ctx context.Context) *storage.KVCon
- func ListAdded(ctx context.Context) []string
- func Logger(ctx context.Context, withArgs ...interface{}) log.Interface
- func OperationLess(ops Operations) func(int, int) bool
- func Set(ctx context.Context, key string, value any)
- func ToAdd(ctx context.Context, newFile ...string)
- type Context
- type GoalDescription
- type Interface
- type Operation
- type OperationFunc
- type OperationHandler
- type Operations
- type Ordering
- type SimpleTask
- type Task
- type TaskBoilerplate
- func (TaskBoilerplate) Begin(context.Context) (Operations, error)
- func (TaskBoilerplate) Check(context.Context) error
- func (TaskBoilerplate) End(context.Context) (Operations, error)
- func (TaskBoilerplate) Finish(context.Context) error
- func (TaskBoilerplate) Run(context.Context) (Operations, error)
- func (TaskBoilerplate) Setup(context.Context) error
- func (TaskBoilerplate) Teardown(context.Context) error
- type TaskDescription
- type Tasks
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUnsupportedTask is returned by Interface.Prepare when the named // task is not implemented by the plugin. ErrUnsupportedTask = fmt.Errorf("this plugin does not support that task") // ErrUnsupportedGoal is returned by Interface.Goal when the named goal // is not defined by the plugin. ErrUnsupportedGoal = fmt.Errorf("this plugin does not support that goal") // ErrBadTaskName is returned when a badly formatted task name is detected. ErrBadTaskName = fmt.Errorf("the task name is badly formatted") )
Functions ¶
func ApplyChanges ¶
ApplyChanges will apply the given changes to the properties.
func AtomicProperties ¶
AtomicProperties executes the given function inside a write lock on the storage object. This allows non-idempotent, atomic modifications to be made to the storage without races.
For example, NEVER RUN:
// NEVER DO THIS! This contains a race condition and will work inconsistently. v := plugin.GetInt(ctx, "foo") plugin.Set(ctx, "foo", v+1)
Instead, you should follow this example:
plugin.AtomicProperties(ctx, func(p storage.KV) { v := p.GetInt("foo") p.Set("foo", v+1) })
func ForCleanup ¶
func ForCleanup(ctx context.Context, newCleaner SimpleTask)
ForCleanup adds the given task to be performed at cleanup time.
func GetDuration ¶
GetDuration returns the value for the given key as a time.Duration.
func GetFloat64 ¶
GetFloat64 returns the value for the given key as a float64.
func GetIntSlice ¶
GetIntSlice returns the value for the given key as an []int.
func GetStringMap ¶
GetStringMap returns the value for the given key as a map[string]any.
func GetStringMapString ¶
GetStringMapString returns the value for the given key as a map[string]string.
func GetStringMapStringSlice ¶
GetStringMapStringSlice returns the value for the given key as a map[string][]string.
func GetStringSlice ¶
GetStringSlice returns the value for the given key as a []string.
func InitializeContext ¶
InitializeContext attaches the plugin.Context to the context.Context.
func ListAdded ¶
ListAdded returns all the files that have been created or added by the tooling since the Context was created.
func Logger ¶
Logger returns the logger for the plugin to use. If any withArgs are passed, the returned logger will have had the hclog.Logger.With function called to set properties on the logger.
func OperationLess ¶
func OperationLess(ops Operations) func(int, int) bool
OperationLess provides a sorting function for Operations.
Types ¶
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context is a container providing the information accessed by the various context.Context accessors used by plugins.
This object is safe to use concurrently. Changes to properties are synchronized as are cleanup functions and add files. However, if your changes are not idempotent, special care must be taken to avoid race conditions. The AtomicProperties function is provided to allow for atomic operations to be safely performed without races.
func NewConfigContext ¶
func NewConfigContext( logger *log.Logger, runtime storage.KV, taskName string, targetName string, pluginName string, cfg *config.Config, ) (*Context, error)
NewConfigContext constructs a new plugin Context, but with the given scopes defined for constructing properties to provide. This is ready to be used with InitializeContext to attach it to a context.Context.
This has the same limitations as NewContext regarding the properties that is mentioned in NewContext.
func NewContext ¶
NewContext constructs a new plugin Context, ready to be used with InitializeContext to attach it to a context.Context.
The properties object here will not be changed when any of the context setters, such as Set or ApplyChanges are used. These will be stored by wrapping the given properties in a storage.KVChanges object. The original caller can apply these changes by using UpdateStorage and StorageChanges together.
func (*Context) ListAdded ¶ added in v0.1.0
ListAdded returns the list of files added to the plugin context.
func (*Context) StorageChanges ¶
StorageChanges clears any changes that were made by callers to the mutator methods on the context.Context and returns them. These can be made permanent by calling UpdateStorage.
func (*Context) UpdateStorage ¶
UpdateStorage allows the owner of the Context to update the properties of the properties object given during construction. None of the mutator functions that work on context.Context are able to make changes to the original properties object as they only apply their changes to a storage.KVChanges wrapper applied during Context construction.
type GoalDescription ¶
type GoalDescription interface { // Name is the top-level name of the task. This is preferable a single, // short verb. It must be all lowercase letters or may contain a hyphen. // This will be the default command-name to use to execute this task and // associated sub-tasks and also must match the first path element of a // SubTaskDescription Name. Name() string // Short is the short description of the task to show the user when showing // usage information for the task. Short() string // Aliases returns other names (possibly shortened names) to grant // implementations of this task. Aliases() []string }
GoalDescription describes a top-level goal.
type Interface ¶
type Interface interface { // Implements will list the tasks that this plugin implements. It may return // an empty list if no task is implemented. A task is only permitted to // implement a single task with a given name. Implements(ctx context.Context) (tasks []TaskDescription, err error) // Goal will return the GoalDefinition for the given goal name, which // provides documentation for the named top-level goal. This method should // return ErrUnsupportedGoal when no such top-level task is defined by this // plugin. Goal(ctx context.Context, name string) (def GoalDescription, err error) // Prepare should return an initialized Task object that is configured using // the given global configuration as well as the task configuration. The // object passed for task configuration is specific to the given taskName. // // The lifecycle of this method needs to be handled such that the return // value from this method must be handled similar to the following: // // task, err := taskInterface.Prepare(ctx, taskName, globalCfg) // if err != nil { // if task != nil { // cancelErr := taskInterface.Cancel(ctx, task) // if cancelErr != nil { // log.Print(cancelErr) // } // } // return err // } // // Once a task is returned from this method, you must either call Cancel // or Close on the Interface with the given task object or risk leaking // resources or having other unfinished working and unexpected results. // // This should return ErrUnsupportedTask if the given taskName does not // match a supported task. Prepare( ctx context.Context, taskName string, ) (task Task, err error) // Cancel must be called when a task is not going to be completed in full. // The implementation will use this opportunity to call teardown and perform // any cleanup actions that have been queued up to try to undo the work done // so far. Cancel(ctx context.Context, task Task) (err error) // Complete must be called when a task has been run to completion. This // allows the task to perform any final teardown and cleanup resources. Complete(ctx context.Context, task Task) (err error) }
Interface is the base interface that all plugins implement.
type Operation ¶
type Operation struct { Order Ordering Action OperationHandler }
Operation is an object that is used to give Order to the Actions that get performed while executing a Stage of a Task.
type OperationFunc ¶
OperationFunc is an implementation of OperationHandler defined as a function.
type OperationHandler ¶
type OperationHandler interface { // Call performs the operation. An error will typically result in // termination of the entire task with the given error. Call(ctx context.Context) error }
OperationHandler defines the type interface for operations. An operation executes some part of a Task.
type Operations ¶
type Operations []Operation
Operations is a list of zero or more Operation objects.
type Ordering ¶
type Ordering int
Ordering is a scheme for prioritizing operations. An Ordering must be in the range of 0-100, inclusive. Lower Ordering values precede larger ones when it comes to determining the order of operations.
type SimpleTask ¶
type SimpleTask func()
SimpleTask is the type of function used for cleanup functions.
func ListCleanupTasks ¶
func ListCleanupTasks(ctx context.Context) []SimpleTask
ListCleanupTasks returns all the cleanup tasks that have been setup so far since the start of this Context. The tasks are returned in the reverse order they were added.
type Task ¶
type Task interface { // Setup should be used exclusively for initial setup of the Task, such as // acquiring resources, setting clients and connections, and other // housekeeping tasks. No operations related to performing the task should // be performed here. Setup(context.Context) error // Check should only execute initial validation and guard functions to // prevent the operation from continuing. No writes or modifications ought // to be performed here. This can also be a reasonable stage at which to // detect and setup property values for later use. Check(context.Context) error // Begin should be used to prepare early stage operations for the task. Begin(context.Context) (Operations, error) // Run should be used to prepare middle stage operations for the task. Run(context.Context) (Operations, error) // End should be used to prepare late stage operations for the task. End(context.Context) (Operations, error) // Finish should be used for any final checks to ensure the task has been // performed correctly and sanely. Modifications should not be performed // at this late stage. Finish(context.Context) error // Teardown should only be used to releasing resources, closing connections, // and internal cleanup. No operations realted to performing the task should // be performed here. Teardown(context.Context) error }
Task provides some operations to help perform a task. The task is executed in a series of stages and if multiple plugins implement a given task, they may be run in parallel. The task operations are executed in the following order:
* Setup
* Check
* Begin (in ascending Order)
* Run (in ascending Order)
* End (in ascending Order)
* Finish
* Teardown
And that's it.
type TaskBoilerplate ¶
type TaskBoilerplate struct{}
TaskBoilerplate is intended at simplifying the implementation of a Task by providing empty, noop implementations for all Task methods. That way a Task only needs to implement the stages and operations it needs to implement.
func (TaskBoilerplate) Begin ¶
func (TaskBoilerplate) Begin(context.Context) (Operations, error)
func (TaskBoilerplate) End ¶
func (TaskBoilerplate) End(context.Context) (Operations, error)
func (TaskBoilerplate) Run ¶
func (TaskBoilerplate) Run(context.Context) (Operations, error)
type TaskDescription ¶
type TaskDescription interface { // Name is a path starting with a leading slash naming the sub-task. The // first element of this path must match a TaskDescription defined by the // given Plugin (or a built-in task). The remaining path elements define a // sub-task of the level above. This is usually of the form of /verb/noun // where short words a preferred and the names must be lowercase and may // contain hyphens. // // The path elements here will become the names of the sub-commands on the // command-line if a user wants to execute a sub-step of a larger task. Name() string // Short is the short description of what this sub-task does. It will be // combined with all other like-named sub-tasks to from the description text // shown when usage help is requested. This description should be very // concise. Short() string // Requires names zero or more sub-task names on which this task depends. // Usually, these will be other sub-tasks that are defined by this plugin. // // Actual sub-task dependencies are calculated by calculating the // requirements of all like-named sub-tasks together. For example, if // /release/publish in plugin A depends on /release/mint and it dapends on // /release/wait in plugin B and both plugins will be executed, then this // task will not be executed until after both /release/wait and // /release/mint have been executed. Requires() []string }
TaskDescription describes a sub-task.
Directories ¶
Path | Synopsis |
---|---|
Package api defines the gRPC interface plugins use over the wire.
|
Package api defines the gRPC interface plugins use over the wire. |
grpc
|
|
client
Package client implements the gRPC client used by the zedpm master process to communicate with all the plugins.
|
Package client implements the gRPC client used by the zedpm master process to communicate with all the plugins. |
service
Package service implements the gRPC service for plugins so plugins can just implement the plugin.Interface and related interfaces.
|
Package service implements the gRPC service for plugins so plugins can just implement the plugin.Interface and related interfaces. |
Package master implements the components for executing goals and sub-tasks across multiple plugins concurrently with proper interleaving and error handling.
|
Package master implements the components for executing goals and sub-tasks across multiple plugins concurrently with proper interleaving and error handling. |
Package metal provides the entry point for implementing the plugin system in a process.
|
Package metal provides the entry point for implementing the plugin system in a process. |
Package translate provides object translation to translate API objects into local plugin objects and vice versa.
|
Package translate provides object translation to translate API objects into local plugin objects and vice versa. |