GithubHelp home page GithubHelp logo

szlabs / go-plugin Goto Github PK

View Code? Open in Web Editor NEW
4.0 5.0 1.0 152 KB

Plugin framework with golang

License: Apache License 2.0

Go 100.00%
golang plugin plugin-manager plugin-system plugin-loader plugins pluggable plugin-repository

go-plugin's Introduction

go-plugin

CircleCI Codacy Badge codebeat badge

go-plugin is intent on providing a plugin framework based on the plugin feature originated from golang 1.8. go-plugin works in the plugin consumer side to handle related stages of running a plugin, including discover, build, load, upgrade, manage, call and unload.

To learn more, check our roadmap.

If you want to do contributions to this project, WELCOME!

Maintainers

Plugin specification

The plugin should follow the specifications below then it can be recognized by go-plugin framework.

Entry method

The plugin should have a single unified and exported entry method with name Execute. The full signature is listed below:

func Execute(ctx context.PluginContext) error {
    return nil
}

The entry method has a plugin context argument which extends the golang context interface and provides extra value operation methods. The detailed declarations of this context interface are shown below:

//ValueContext defines behaviors of handling values with string keys
type ValueContext interface {
    //Get value by the key
    GetValue(key string) interface{}

    //Set value to context
    SetValue(key string, value interface{})
}

//PluginContext help to provide related information/parameters to the
//plugin execution entry method.
//PluginContext inherits all from the context.Context
type PluginContext interface {
    context.Context
    ValueContext
}

go-plugin provides a base plugin context for using.

import "github.com/szlabs/go-plugin/pkg/context"

context.BasePluginContext

Metadata json file

go-plugin use a json file plugin.json to define and describe the plugin metadata. An example:

{
    "name": "go-plugin",
    "version": "0.1.0",
    "description": "A go plugin management tool",
    "maintainers": ["[email protected]"],
    "home": "https://github.com/szlabs/go-plugin.git",
    "source": {
        "mode": "local_so",
        "path": "sample.so"
    },
    "http_services": {
        "driver": "beego",
        "routes": [
            { "route": "/api/plugin/sample/:id", "method": "GET", "label": "plugin.get" },
            { "route": "/api/plugin/samples", "method": "POST", "label": "plugin.post" }
        ]
    }
}

The spec details:

Field Description Required Supported
name Name of the plugin Y Y
version Plugin version with semver 2 Y Y
description One sentence to describe the plugin N Y
maintainers A list of mails of maintainers N Y
home The home site or repository site N Y
source.mode The mode of the plugin. local_so for local so file; remote_git for remote source repository Y Y
source.path The so file path or the remote git repositry Y Y
http_services.driver The name of the http service driver which is used to enable the http services Y N
http_services.routes A route list to map the service endpoints to the plugin method with labels Y N
http_services.routes[i].route The service endpoint definition Y N
http_services.routes[i].method The http method to apply on the route Y N
http_services.routes[i].label Add the label to the plugin context when calling the plugin entry method Y N

Plugin Management

The following sample code shows how to manage the plugins with go-plugin.

//Hello ...
type Hello struct {
    Name string
}

func main() {
    wk, err := os.Getwd()
    if err != nil {
        PrintError(err)
    }
    pluginBaseDir := filepath.Join(wk, "plugins")
    log.Printf("[INFO]: Plugin base dir: %s\n", pluginBaseDir)

    pluginManager := plugin.DefaultManager
    pluginManager.SetPluginBaseDir(pluginBaseDir)
    pluginManager.LoadPlugins()

    spec, executor, err := pluginManager.GetPlugin("sample")
    if err != nil {
       PrintError(err)
    }

    log.Printf("[INFO]: Plugin '%s' loaded with version '%s'\n", spec.Name, spec.Version)
    pContext := context.Background()
    pContext.SetValue("sample", &Hello{"hello go-plugin"})
    executor(pContext)
}

//PrintError ...
func PrintError(err error) {
    log.Printf("[Error]: %s\n", err)
    os.Exit(1)
}

Develop a plugin

  • Step 1: Implement func Execute(ctx context.PluginContext) error
  • Step 2: Build the plugin with command go build -buildmode=plugin -o sample.so sample.go

NOTES:

  • If the logic is loop logic in goroutine, please make sure there is an exit way by listening the context done() channel or your goroutine may escape away when unloading the plugin
  • If you need to handle multiple scenarios, just call your sub logic based on some values which are passed by plugin context. e.g:
func Execute(ctx context.PluginContext) error {
    label := ctx.GetValue("label")
    if label == nil {
        return errors.New("label is not set in the plugin context")
    }

    labelV := fmt.Sprintf("%s", label)
    switch labelV {
        case "case1":
          return call_subMethod1()
        case "case 2":
          return call_subMethod12()
        default:
          return errors.New("not suppotred")
    }
}

Next steps

  • Package the plugin.json and the so file as single *.plg file (with gzip)
  • Build the plugin from source code @git repo
  • Monitor and detect the plugin change in the plugin base dir
  • Plugin hot upgrade
  • Support http service onboarding drivers (beego first)
  • Load plugins from internet
  • Provide plugin metrics
  • Enable API and run as rest services
  • Provide GUI for plugin management
  • Provided hooks for the lifecycle of plugin
  • Add test cases and setup CI/CD

Issues

  • Currently plugins are only supported on Linux and macOS (Extened from golang plugin)
  • Memory issues if discard a loaded so

go-plugin's People

Contributors

codacy-badger avatar steven-zou avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

xserve98

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.