Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for plugins in fnext #1385

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down Expand Up @@ -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")
Expand Down
3 changes: 0 additions & 3 deletions api/agent/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions api/agent/lb_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type lbAgent struct {
callListeners []fnext.CallListener
rp pool.RunnerPool
placer pool.Placer
callOverrider CallOverrider
callOverrider fnext.CallOverrider
shutWg *common.WaitGroup
}

Expand Down Expand Up @@ -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")
Expand Down
6 changes: 3 additions & 3 deletions fnext/listeners.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
8 changes: 8 additions & 0 deletions fnext/overrider.go
Original file line number Diff line number Diff line change
@@ -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 changes: 98 additions & 0 deletions fnext/plugin.go
Original file line number Diff line number Diff line change
@@ -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
}