Skip to content
This repository has been archived by the owner on Oct 27, 2020. It is now read-only.

Commit

Permalink
fixing bug
Browse files Browse the repository at this point in the history
  • Loading branch information
GRECO, FRANK committed Aug 12, 2017
1 parent a9b77f5 commit 680b71c
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 106 deletions.
46 changes: 46 additions & 0 deletions plugins/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,62 @@ package plugins

import (
"context"
"fmt"
"net/http"
pluginPkg "plugin"

"github.com/northwesternmutual/kanali/config"
"github.com/northwesternmutual/kanali/controller"
"github.com/northwesternmutual/kanali/spec"
"github.com/northwesternmutual/kanali/utils"
"github.com/opentracing/opentracing-go"
"github.com/spf13/viper"
)

const pluginSymbolName = "Plugin"

// Plugin is an interface that is used for every Plugin used by Kanali.
// If external plugins are developed, they also must conform to this interface.
type Plugin interface {
OnRequest(ctx context.Context, proxy spec.APIProxy, ctlr controller.Controller, req *http.Request, span opentracing.Span) error
OnResponse(ctx context.Context, proxy spec.APIProxy, ctlr controller.Controller, req *http.Request, resp *http.Response, span opentracing.Span) error
}

// GetPlugin will use the Go plugin package and extract
// the plugin
func GetPlugin(plugin spec.Plugin) (*Plugin, error) {
path, err := utils.GetAbsPath(viper.GetString(config.FlagPluginsLocation.GetLong()))
if err != nil {
return nil, utils.StatusError{Code: http.StatusInternalServerError, Err: fmt.Errorf("file path %s could not be found", viper.GetString("plugins-path"))}
}

plug, err := pluginPkg.Open(fmt.Sprintf("%s/%s.so",
path,
plugin.GetFileName(),
))
if err != nil {
return nil, utils.StatusError{
Code: http.StatusInternalServerError,
Err: fmt.Errorf("could not open plugin %s: %s", plugin.Name, err.Error()),
}
}

symPlug, err := plug.Lookup(pluginSymbolName)
if err != nil {
return nil, utils.StatusError{
Code: http.StatusInternalServerError,
Err: err,
}
}

var p Plugin
p, ok := symPlug.(Plugin)
if !ok {
return nil, utils.StatusError{
Code: http.StatusInternalServerError,
Err: fmt.Errorf("plugin %s must implement the Plugin interface", plugin.Name),
}
}

return &p, nil
}
57 changes: 9 additions & 48 deletions steps/pluginsonrequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ import (
"errors"
"fmt"
"net/http"
pluginPkg "plugin"

"github.com/Sirupsen/logrus"
"github.com/northwesternmutual/kanali/controller"
"github.com/northwesternmutual/kanali/plugins"
"github.com/northwesternmutual/kanali/spec"
"github.com/northwesternmutual/kanali/utils"
"github.com/opentracing/opentracing-go"
"github.com/spf13/viper"
)

// PluginsOnRequestStep is factory that defines a step responsible for
Expand All @@ -58,65 +56,28 @@ func (step PluginsOnRequestStep) Do(ctx context.Context, c *controller.Controlle
}

for _, plugin := range proxy.Spec.Plugins {
if err := doExecutePlugin(ctx, proxy, *c, r, trace, plugin); err != nil {
p, err := plugins.GetPlugin(plugin)
if err != nil {
return err
}
}

return nil
}

func doExecutePlugin(ctx context.Context, proxy spec.APIProxy, c controller.Controller, r *http.Request, trace opentracing.Span, plugin spec.Plugin) error {
sp := opentracing.StartSpan(fmt.Sprintf("PLUGIN: ON_REQUEST: %s", plugin.Name), opentracing.ChildOf(trace.Context()))
defer sp.Finish()

path, err := utils.GetAbsPath(viper.GetString("plugins-location"))
if err != nil {
return utils.StatusError{Code: http.StatusInternalServerError, Err: fmt.Errorf("file path %s could not be found", viper.GetString("plugins-path"))}
}

plug, err := pluginPkg.Open(fmt.Sprintf("%s/%s.so",
path,
plugin.GetFileName(),
))
if err != nil {
return utils.StatusError{
Code: http.StatusInternalServerError,
Err: fmt.Errorf("could not open plugin %s: %s", plugin.Name, err.Error()),
}
}

symPlug, err := plug.Lookup("Plugin")
if err != nil {
return utils.StatusError{
Code: http.StatusInternalServerError,
Err: err,
}
}

var p plugins.Plugin
p, ok := symPlug.(plugins.Plugin)
if !ok {
return utils.StatusError{
Code: http.StatusInternalServerError,
Err: fmt.Errorf("plugin %s must implement the Plugin interface", plugin.Name),
if err := doOnRequest(ctx, plugin.Name, proxy, *c, r, trace, *p); err != nil {
return err
}
}

if err := doOnRequest(ctx, proxy, c, r, sp, p); err != nil {
return err
}

return nil
}

func doOnRequest(ctx context.Context, proxy spec.APIProxy, ctlr controller.Controller, req *http.Request, span opentracing.Span, p plugins.Plugin) (e error) {
func doOnRequest(ctx context.Context, name string, proxy spec.APIProxy, ctlr controller.Controller, req *http.Request, span opentracing.Span, p plugins.Plugin) (e error) {
defer func() {
if r := recover(); r != nil {
logrus.Errorf("OnRequest paniced: %v", r)
e = errors.New("OnRequest paniced")
}
}()

sp := opentracing.StartSpan(fmt.Sprintf("PLUGIN: ON_REQUEST: %s", name), opentracing.ChildOf(span.Context()))
defer sp.Finish()

if err := p.OnRequest(ctx, proxy, ctlr, req, span); err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions steps/pluginsonrequest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestPluginsOnRequestGetName(t *testing.T) {
}

func TestDoOnRequest(t *testing.T) {
assert.Equal(t, doOnRequest(context.Background(), spec.APIProxy{}, controller.Controller{}, nil, opentracing.StartSpan("test span"), fakePanicPlugin{}).Error(), "OnRequest paniced")
assert.Equal(t, doOnRequest(context.Background(), spec.APIProxy{}, controller.Controller{}, nil, opentracing.StartSpan("test span"), fakeErrorPlugin{}).Error(), "error")
assert.Nil(t, doOnRequest(context.Background(), spec.APIProxy{}, controller.Controller{}, nil, opentracing.StartSpan("test span"), fakeSuccessPlugin{}))
assert.Equal(t, doOnRequest(context.Background(), "name", spec.APIProxy{}, controller.Controller{}, nil, opentracing.StartSpan("test span"), fakePanicPlugin{}).Error(), "OnRequest paniced")
assert.Equal(t, doOnRequest(context.Background(), "name", spec.APIProxy{}, controller.Controller{}, nil, opentracing.StartSpan("test span"), fakeErrorPlugin{}).Error(), "error")
assert.Nil(t, doOnRequest(context.Background(), "name", spec.APIProxy{}, controller.Controller{}, nil, opentracing.StartSpan("test span"), fakeSuccessPlugin{}))
}
60 changes: 8 additions & 52 deletions steps/pluginsonresponse.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ import (
"errors"
"fmt"
"net/http"
pluginPkg "plugin"

"github.com/Sirupsen/logrus"
"github.com/northwesternmutual/kanali/controller"
"github.com/northwesternmutual/kanali/plugins"
"github.com/northwesternmutual/kanali/spec"
"github.com/northwesternmutual/kanali/utils"
"github.com/opentracing/opentracing-go"
"github.com/spf13/viper"
)

// PluginsOnResponseStep is factory that defines a step responsible for
Expand All @@ -47,9 +45,6 @@ func (step PluginsOnResponseStep) GetName() string {

// Do executes the logic of the PluginsOnResponseStep step
func (step PluginsOnResponseStep) Do(ctx context.Context, c *controller.Controller, w http.ResponseWriter, r *http.Request, resp *http.Response, trace opentracing.Span) error {

// retreive the current proxy which holds
// the plugins that should be executed, if any
untypedProxy, err := spec.ProxyStore.Get(r.URL.Path)
if err != nil || untypedProxy == nil {
return utils.StatusError{Code: http.StatusNotFound, Err: errors.New("proxy not found")}
Expand All @@ -60,69 +55,30 @@ func (step PluginsOnResponseStep) Do(ctx context.Context, c *controller.Controll
return utils.StatusError{Code: http.StatusNotFound, Err: errors.New("proxy not found")}
}

// iterate over all of the plugins associated with this proxy
for _, plugin := range proxy.Spec.Plugins {

sp := opentracing.StartSpan(fmt.Sprintf("PLUGIN: ON_RESPONSE: %s", plugin.Name), opentracing.ChildOf(trace.Context()))

path, err := utils.GetAbsPath(viper.GetString("plugins-location"))
if err != nil {
return utils.StatusError{Code: http.StatusInternalServerError, Err: fmt.Errorf("file path %s could not be found", viper.GetString("plugins-path"))}
}

// open the plugin module using the standard Go
// plugin package.
plug, err := pluginPkg.Open(fmt.Sprintf("%s/%s.so",
path,
plugin.GetFileName(),
))
if err != nil {
return utils.StatusError{
Code: http.StatusInternalServerError,
Err: fmt.Errorf("could not open plugin %s", plugin.Name),
}
}

// lookup an exported variable from our plugin module
symPlug, err := plug.Lookup("Plugin")
p, err := plugins.GetPlugin(plugin)
if err != nil {
return utils.StatusError{
Code: http.StatusInternalServerError,
Err: err,
}
}

var p plugins.Plugin
p, ok := symPlug.(plugins.Plugin)
if !ok {
return utils.StatusError{
Code: http.StatusInternalServerError,
Err: fmt.Errorf("plugin %s must implement the Plugin interface", plugin.Name),
}
return err
}

// execute the OnResponse function of our current plugin
if err := doOnResponse(ctx, proxy, *c, r, resp, sp, p); err != nil {
if err := doOnResponse(ctx, plugin.Name, proxy, *c, r, resp, trace, *p); err != nil {
return err
}

sp.Finish()

}

// all plugins, if any, have been executed
// without any error
return nil

}

func doOnResponse(ctx context.Context, proxy spec.APIProxy, ctlr controller.Controller, req *http.Request, resp *http.Response, span opentracing.Span, p plugins.Plugin) (e error) {
func doOnResponse(ctx context.Context, name string, proxy spec.APIProxy, ctlr controller.Controller, req *http.Request, resp *http.Response, span opentracing.Span, p plugins.Plugin) (e error) {
defer func() {
if r := recover(); r != nil {
logrus.Errorf("OnResponse paniced: %v", r)
e = errors.New("OnResponse paniced")
}
}()

sp := opentracing.StartSpan(fmt.Sprintf("PLUGIN: ON_RESPONSE: %s", name), opentracing.ChildOf(span.Context()))
defer sp.Finish()

if err := p.OnResponse(ctx, proxy, ctlr, req, resp, span); err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions steps/pluginsonresponse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestPluginsOnResponseGetName(t *testing.T) {
}

func TestDoOnResponse(t *testing.T) {
assert.Equal(t, doOnResponse(context.Background(), spec.APIProxy{}, controller.Controller{}, nil, nil, opentracing.StartSpan("test span"), fakePanicPlugin{}).Error(), "OnResponse paniced")
assert.Equal(t, doOnResponse(context.Background(), spec.APIProxy{}, controller.Controller{}, nil, nil, opentracing.StartSpan("test span"), fakeErrorPlugin{}).Error(), "error")
assert.Nil(t, doOnResponse(context.Background(), spec.APIProxy{}, controller.Controller{}, nil, nil, opentracing.StartSpan("test span"), fakeSuccessPlugin{}))
assert.Equal(t, doOnResponse(context.Background(), "name", spec.APIProxy{}, controller.Controller{}, nil, nil, opentracing.StartSpan("test span"), fakePanicPlugin{}).Error(), "OnResponse paniced")
assert.Equal(t, doOnResponse(context.Background(), "name", spec.APIProxy{}, controller.Controller{}, nil, nil, opentracing.StartSpan("test span"), fakeErrorPlugin{}).Error(), "error")
assert.Nil(t, doOnResponse(context.Background(), "name", spec.APIProxy{}, controller.Controller{}, nil, nil, opentracing.StartSpan("test span"), fakeSuccessPlugin{}))
}

0 comments on commit 680b71c

Please sign in to comment.