{"id":13564406,"url":"https://github.com/pierods/pluginator","last_synced_at":"2026-01-16T18:38:17.852Z","repository":{"id":144201571,"uuid":"95437766","full_name":"pierods/pluginator","owner":"pierods","description":"pluginator is a plugin manager for scripted go, with plugins on filesystem or consul","archived":false,"fork":false,"pushed_at":"2017-07-13T08:03:36.000Z","size":32,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-04T17:47:31.217Z","etag":null,"topics":["consul","go","golang","plugin","plugin-loader","plugin-manager","service-configuration","service-discovery"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pierods.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-06-26T11:01:03.000Z","updated_at":"2021-04-04T06:57:22.000Z","dependencies_parsed_at":"2023-06-18T03:45:56.234Z","dependency_job_id":null,"html_url":"https://github.com/pierods/pluginator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pierods%2Fpluginator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pierods%2Fpluginator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pierods%2Fpluginator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pierods%2Fpluginator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pierods","download_url":"https://codeload.github.com/pierods/pluginator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247082968,"owners_count":20880753,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["consul","go","golang","plugin","plugin-loader","plugin-manager","service-configuration","service-discovery"],"created_at":"2024-08-01T13:01:30.866Z","updated_at":"2026-01-16T18:38:17.823Z","avatar_url":"https://github.com/pierods.png","language":"Go","readme":"# Pluginator - a plugin manager for scripted Go\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![](https://godoc.org/github.com/pierods/pluginator?status.svg)](http://godoc.org/github.com/pierods/pluginator)\n[![Go Report Card](https://goreportcard.com/badge/github.com/pierods/pluginator)](https://goreportcard.com/report/github.com/pierods/pluginator)\n[![Build Status](https://travis-ci.org/pierods/pluginator.svg?branch=master)](https://travis-ci.org/pierods/pluginator)\n\nPluginator is a plugin manager/loader for plugins written in Go. Plugins can be dropped in source code form into a watched folder,\nor added as subkeys to a consul key, as source code as well. Pluginator will pick them up, compile them, load the resulting libraries\nand make them available to its clients.\n\nPlugins can be edited in-place, added or removed. Pluginator will synchronize its internal registry with the watched folder (or consul\nkey) and notify its clients.\n\nA higher level client of Pluginator can then decide what makes a valid plugin, and what can be in a plugin.\n\n## Motivation\nScripting engines for Go are already available, like [otto](https://github.com/robertkrimen/otto), which executes javascript, or [go-lua](https://github.com/Shopify/go-lua), which executes lua.\n\nHowever, there are three drawbacks to the scripting engine approach to plugins, which can be important or not for your project. The first is the loss of speed, which of course is not a problem for some applications.\nThe second is the full support for the target language, which limits the power of the scripting engine itself. Some scripting engines are very up-to-date with their target language,\nbut they inevitably fall behind.\n\nThe third drawback, maybe the most important, is the loss of expressivity. When a host language (Go in this case) is chosen for a domain problem, it's usually because it is \nthe most expressive language for the specific problem at hand. Having to write plugins in another language causes a loss of that expressive power, and also, because of the \nlearning curve of the target language, a further degradation in expressive power.\n\n### Why Consul\nNowadays, it's very common to work with many instances of a program (think microservices). Having software that is not dependent on physical location of files is much more convenient.\n\n## Limitations\nMainly three: a go toolchain must be installed on the host machine, Go \u003e= 1.8 must be used to compile pluginator and for the go toolchain, and the target machine can only be linux.\n\n## Installation\nTo compile pluginator, you need the consul Go client, fsnotify and Google UUID:\n  \n ```bash\n    go get github.com/hashicorp/consul/api\n    go get github.com/google/uuid  # only for testing\n    go get github.com/fsnotify/fsnotify\n \n ```\nYou can then build it:\n\n```bash\n    cd pluginator\n    go build\n```\n\nYou must also install a go toolchain on the host machine. Follow the instructions on Go's download page, [this one](https://golang.org/doc/install?download=go1.8.3.linux-amd64.tar.gz) for 1.8.3 for example\n\n## Usage\nYou can instantiate Pluginator in file mode or consul mode:\n\n```Go\n    pluginator, err := NewPluginatorF(\"/a/chosen/plugin/directory\")\n    if err != nil {\n        t.Fatal(err)\n    }\n```\n\n```Go\n    cw, err := newConsulWatcher(\"aconsulhost\", 8500, \"my.consul.key.for.plugins\")\n    if err != nil {\n        t.Fatal(err)\n    }\n```\n\nYour program can then subscribe to scan/add/modify/remove events:\n\n```Go\n    func ScanSubscriber(pluginNamesAndLibs map[string]*PluginContent) {\n        // do something about plugins having been addded\n    }\n    \n    func RemoveSubscriber(pluginName string, pluginLib *PluginContent) {\n        // do something about a plugin having been removed\n    }\n    \n    func UpdateSubscriber(pluginName string, pluginLib *PluginContent) {\n        // do something about a plugin having been changed\n    }\n    \n    func AddSubscriber(pluginName string, pluginLib *PluginContent) {\n        // do something about a plugin having been added\n    }\n    \n    pluginator.SubscribeScan(ScanSubscriber)\n    pluginator.SubscribeRemove(RemoveSubscriber)\n    pluginator.SubscribeAdd(AddSubscriber)\n    pluginator.SubscribeUpdate(UpdateSubscribe)\n\n```\n\nYou can then drop a go plugin in the plugin directory, or add it to consul (with the Go api or simply with an http client like curl):\n\n```Go\n    import \"github.com/hashicorp/consul/api\"\n    \n    config := api.DefaultConfig()\n    \t(*config).Address = \"localhost:8500\"\n    \n    \tclient, err := api.NewClient(config)\n    \tif err != nil {\n    \t\t...\n    \t}\n    \n    \tkv := client.KV()\n    \t\n        p := \u0026api.KVPair{\n            Key:   \"my.plugin.key.\" + \"myplugin.go\"\n            Value: []byte(myPlugin),\n        }\n    \n        _, err = kv.Put(p, nil)\n        if err != nil {\n            ....\n        }\n\n```\nPluginator will notify its subscriber with a plugin's name, exported symbols and source code:\n\n```Go\n    type PluginContent struct {\n        Lib  *plugin.Plugin\n        Code string\n    }\n```\n\nWhen you are done with pluginator, terminate it:\n\n```Go\n    pluginator.Terminate()\n```\n\n## Rules for plugins\nA Pluginator plugin must:\n + be in package main\n + be in a filename ending in .go (or be a consul key with a name ending in .go)\n + can have a func main() stub for compiling locally before sending to Pluginator \n  \nHere is an example plugin (more in the tests):\n\n```Go\n    package main\n    \n    func Add(x, y int) int {\n        return x + y\n    }\n    \n    func main() {\n    }\n```\n\n\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpierods%2Fpluginator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpierods%2Fpluginator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpierods%2Fpluginator/lists"}