Add support for plugins in fnext

This commit is contained in:
Richard Connon
2019-01-07 16:00:04 +00:00
parent 6e92377bf1
commit 4a72a7b2fd
6 changed files with 113 additions and 10 deletions

View File

@@ -109,7 +109,7 @@ type agent struct {
shutWg *common.WaitGroup
shutonce sync.Once
callOverrider CallOverrider
callOverrider fnext.CallOverrider
// deferred actions to call at end of initialisation
onStartup []func()
}
@@ -203,7 +203,7 @@ func WithDockerDriver(drv drivers.Driver) Option {
}
// WithCallOverrider registers register a CallOverrider to modify a Call and extensions on call construction
func WithCallOverrider(fn CallOverrider) Option {
func WithCallOverrider(fn fnext.CallOverrider) Option {
return func(a *agent) error {
if a.callOverrider != nil {
return errors.New("lb-agent call overriders already exists")

View File

@@ -39,9 +39,6 @@ type Call interface {
End(ctx context.Context, err error) error
}
// Interceptor in GetCall
type CallOverrider func(*models.Call, map[string]string) (map[string]string, error)
// TODO build w/o closures... lazy
type CallOpt func(c *call) error

View File

@@ -24,7 +24,7 @@ type lbAgent struct {
callListeners []fnext.CallListener
rp pool.RunnerPool
placer pool.Placer
callOverrider CallOverrider
callOverrider fnext.CallOverrider
shutWg *common.WaitGroup
}
@@ -71,7 +71,7 @@ func WithLBAgentConfig(cfg *Config) LBAgentOption {
}
// LB agents can use this to register a CallOverrider to modify a Call and extensions
func WithLBCallOverrider(fn CallOverrider) LBAgentOption {
func WithLBCallOverrider(fn fnext.CallOverrider) LBAgentOption {
return func(a *lbAgent) error {
if a.callOverrider != nil {
return errors.New("lb-agent call overriders already exists")

View File

@@ -57,7 +57,7 @@ type FnListener interface {
AfterFnDelete(ctx context.Context, fnID string) error
}
//// TriggerListener enables callbacks around Trigger events
// TriggerListener enables callbacks around Trigger events
type TriggerListener interface {
// BeforeTriggerCreate called before trigger created in the datastore
BeforeTriggerCreate(ctx context.Context, trigger *models.Trigger) error
@@ -68,9 +68,9 @@ type TriggerListener interface {
// AfterTriggerUpdate called after trigger updated in datastore
AfterTriggerUpdate(ctx context.Context, trigger *models.Trigger) error
// BeforeTriggerDelete called before trigger deleted from the datastore
BeforeTriggerDelete(ctx context.Context, triggerId string) error
BeforeTriggerDelete(ctx context.Context, triggerID string) error
// AfterTriggerDelete called after trigger deleted from the datastore
AfterTriggerDelete(ctx context.Context, triggerId string) error
AfterTriggerDelete(ctx context.Context, triggerID string) error
}
// CallListener enables callbacks around Call events.

8
fnext/overrider.go Normal file
View File

@@ -0,0 +1,8 @@
package fnext
import (
"github.com/fnproject/fn/api/models"
)
// CallOverrider is an interceptor in GetCall which can modify Call and extensions
type CallOverrider func(*models.Call, map[string]string) (map[string]string, error)

98
fnext/plugin.go Normal file
View File

@@ -0,0 +1,98 @@
package fnext
import (
"fmt"
"plugin"
)
const (
listenerSymbolName = "Listener"
middlewareSymbolName = "Handle"
overriderSymbolName = "Overrider"
)
func symbolFromPlugin(path, symbolName string) (plugin.Symbol, error) {
plugin, err := plugin.Open(path)
if err != nil {
return nil, err
}
return plugin.Lookup(symbolName)
}
// NewPluginMiddleware creates an Fn Middleware from a Golang plugin
func NewPluginMiddleware(path string) (Middleware, error) {
handleSymbol, err := symbolFromPlugin(path, middlewareSymbolName)
if err != nil {
return nil, err
}
handler, ok := handleSymbol.(*MiddlewareFunc)
if !ok {
return nil, fmt.Errorf("%s is not a valid middleware function in plugin: %s", middlewareSymbolName, path)
}
return handler, nil
}
// NewPluginAppListener creates an Fn AppListener from a Golang plugin
func NewPluginAppListener(path string) (AppListener, error) {
listenerSymbol, err := symbolFromPlugin(path, listenerSymbolName)
if err != nil {
return nil, err
}
callListener, ok := listenerSymbol.(AppListener)
if !ok {
return nil, fmt.Errorf("%s is not a AppListener", listenerSymbolName)
}
return callListener, nil
}
// NewPluginFnListener creates an Fn FnListener from a Golang plugin
func NewPluginFnListener(path string) (FnListener, error) {
listenerSymbol, err := symbolFromPlugin(path, listenerSymbolName)
if err != nil {
return nil, err
}
callListener, ok := listenerSymbol.(FnListener)
if !ok {
return nil, fmt.Errorf("%s is not a FnListener", listenerSymbolName)
}
return callListener, nil
}
// NewPluginTriggerListener creates an Trigger TriggerListener from a Golang plugin
func NewPluginTriggerListener(path string) (TriggerListener, error) {
listenerSymbol, err := symbolFromPlugin(path, listenerSymbolName)
if err != nil {
return nil, err
}
callListener, ok := listenerSymbol.(TriggerListener)
if !ok {
return nil, fmt.Errorf("%s is not a TriggerListener", listenerSymbolName)
}
return callListener, nil
}
// NewPluginCallListener creates an Fn CallListener from a Golang plugin
func NewPluginCallListener(path string) (CallListener, error) {
listenerSymbol, err := symbolFromPlugin(path, listenerSymbolName)
if err != nil {
return nil, err
}
callListener, ok := listenerSymbol.(CallListener)
if !ok {
return nil, fmt.Errorf("%s is not a CallListener", listenerSymbolName)
}
return callListener, nil
}
// NewPluginCallOverrider creates an Fn CallOverrider from a Golang plugin
func NewPluginCallOverrider(path string) (CallOverrider, error) {
overriderSymbol, err := symbolFromPlugin(path, overriderSymbolName)
if err != nil {
return nil, err
}
callOverrider, ok := overriderSymbol.(*CallOverrider)
if !ok {
return nil, fmt.Errorf("%s is not a valid call overrider in plugin: %s", overriderSymbolName, path)
}
return *callOverrider, nil
}