GithubHelp home page GithubHelp logo

matt-dunleavy / plugin-manager Goto Github PK

View Code? Open in Web Editor NEW
2.0 1.0 0.0 5.42 MB

A simple and flexible plugin management library for Go applications.

License: MIT License

Go 100.00%
dynamic-plugin dynamic-plugin-loading dynamic-plugins go plugin plugin-loader plugin-manager plugin-system plugins hot-reload-plugin

plugin-manager's Introduction

Plugin Manager for Go

A robust and flexible plugin management library for Go applications.

Features
  • Dynamic Loading and Unloading

  • Versioning and Dependency Management

  • Hot-Reloading and Lazy Loading

  • Event System for Lifecycle Events

  • Enhanced Sandboxing for improved security

  • Metrics Collection for Plugin Performance

Deployment and Updates Simplified
  • Automatic Discovery (directory)
  • Remote Plugin Repository
  • Automated Plugin Update System
  • Digital Signature Verification

Easy deployment of your plugin repository with Redbean!

Getting Started

Obtain the latest version of the plugin-manager library with the Go package manager (recommended):

go get github.com/matt-dunleavy/plugin-manager

Or clone the repository to your local machine using the Git Command Line by running the following command in your terminal:

git clone https://github.com/matt-dunleavy/plugin-manager.git
cd plugin-manager

After you've obtained the library, import the package into your source code:

import "github.com/matt-dunleavy/plugin-manager"

Usage

Visit to the examples directory for full-featured implementations.

Initialize a New Plugin Manager

Create a new plugin manager instance at the start of your application.

manager, err := pm.NewManager("plugins.json", "./plugins", "public_key.pem")

Parameters:

  • configPath (string): Path to the JSON configuration file for managing enabled/disabled plugins. ("plugins.json")
  • pluginDir (string): Directory where plugins are stored. ("./plugins")
  • publicKeyPath (string): Path to the public key file used for verifying plugin signatures. ("public_key.pem")

Returns:

  • *Manager: Pointer to the newly created Manager instance.
  • error: Any error encountered during initialization.

Load a Plugin

Load a plugin from the specified path into memory, making it available for execution.

err = manager.LoadPlugin("./plugins/myplugin.so")

Parameters:

  • path (string): Path to the plugin file (.so extension).

Returns:

  • error: Any error encountered during the loading process.

Execute (Run) a Plugin

Run a loaded plugin's Execute() method.

err = manager.ExecutePlugin("MyPlugin")

Parameters:

  • name (string): Name of the plugin to execute.

Returns:

  • error: Any error encountered during plugin execution.

Unload a Plugin

Safely remove a plugin from memory when it's no longer needed.

err = manager.UnloadPlugin("MyPlugin")

Parameters:

  • name (string): Name of the plugin to unload.

Returns:

  • error: Any error encountered during the unloading process.

Hot-Reload a Plugin

Update a loaded plugin to a new version while the application is running (without stopping the application).

err = manager.HotReload("MyPlugin", "./plugins/myplugin_v2.so")

Parameters:

  • name (string): Name of the plugin to hot-reload.
  • path (string): Path to the new version of the plugin.

Returns:

  • error: Any error encountered during the hot-reload process.

Enable Automatic Plugin Discovery

Automatically discover and load all plugins from a specified directory.

err = manager.DiscoverPlugins("./plugins")

Parameters:

  • dir (string): Directory to search for plugins.

Returns:

  • error: Any error encountered during the discovery process.

Subscribe to Plugin Events

Subscribes to a specific plugin event, executing the provided function when the event occurs. Use this function to set up event handlers for various plugin lifecycle events.

manager.SubscribeToEvent("PluginLoaded", func(e pm.Event) {
	fmt.Printf("Plugin loaded: %s\n", e.(pm.PluginLoadedEvent).PluginName)
})

Parameters:

  • eventName (string): Name of the event to subscribe to (e.g., "PluginLoaded").
  • handler (func(Event)): Function to execute when the event occurs.

Returns: None

Creating a plugin

Plugins must implement the Plugin interface.

Plugin (struct)

The Plugin struct defines the basic structure of your plugin. It can be empty if your plugin doesn't need to store any state, or you can add fields if your plugin needs to maintain state across method calls.

type MyPlugin struct{}

Metadata()

The Metadata() method returns metadata about the plugin, including the Name, Version, and Dependencies (a map of other plugins that this plugin depends on, with the key being the plugin's name, and the value being the version constraint).

func (p *MyPlugin) Metadata() pm.PluginMetadata {
    return pm.PluginMetadata{
        Name:         "MyPlugin",
        Version:      "1.0.0",
        Dependencies: map[string]string{},
    }
}

Preload()

The Preload() method is called before the plugin is fully loaded. Use it for any setup that needs to happen before initialization.

func (p *MyPlugin) PreLoad() error {
    fmt.Println("MyPlugin pre-load")
    return nil
}

Init()

The Init() method is called to initialize the plugin. Use it to set up any resources or state the plugin needs.

func (p *MyPlugin) Init() error {
    fmt.Println("MyPlugin initialized")
    return nil
}

PostLoad()

The PostLoad() method is called after the plugin is fully loaded. Use it for any final setup steps.

func (p *MyPlugin) PostLoad() error {
    fmt.Println("MyPlugin post-load")
    return nil
}

Execute()

Execute() is the main method of your plugin. It is called when the plugin manager executes your plugin.

func (p *MyPlugin) Execute() error {
    fmt.Println("MyPlugin executed")
    return nil
}

PreUnload()

The PreUnload() method is called before the plugin is unloaded. Use it to prepare for shutdown.

func (p *MyPlugin) PreUnload() error {
    fmt.Println("MyPlugin pre-unload")
    return nil
}

Shutdown()

The Shutdown() method is called when the plugin is being unloaded. Use it to clean up any resources the plugin has allocated.

func (p *MyPlugin) Shutdown() error {
    fmt.Println("MyPlugin shut down")
    return nil
}

Plugin Variable

This variable is how the plugin manager discovers your plugin. It must be named Plugin and be of the type that implements the plugin interface.

var Plugin MyPlugin

Important

Each of these methods should return an error if something goes wrong during their execution. Returning nil indicates successful completion.

Note

When implementing your own plugin, you would replace the fmt.Println statements with your actual plugin logic. The PreLoad, PostLoad, PreUnload, and Shutdown methods allow you to manage the lifecycle of your plugin, while Init and Execute form the core functionality.

Compiling Plugins

Compile a plugin using the standard Go compiler toolchain by setting the -buildmode flag to plugin:

go build -buildmode=plugin -o myplugin.so myplugin.go

Configuration

The plugin manager uses a JSON configuration file to keep track of enabled plugins. Here's an example plugins.json:

{
  "enabled": {
    "MyPlugin": true,
    "AnotherPlugin": false
  }
}

Simplified Deployment Plugin Repositories

An efficient and straightforward way to deploy and manage remote plugin repositories.

Benefits

  1. Simplified Management: Manage your entire plugin repository with a single file.
  2. Reduced Dependencies: No need for complex web server setups or databases.
  3. Easy Updates: Update your plugin repository by simply replacing the Redbean executable.
  4. Scalability: Redbean can handle repositories of various sizes efficiently.

Advantages

  • Security: Redbean includes built-in security features, reducing the attack surface of your plugin repository.
  • Performance: As a compiled C application, Redbean offers excellent performance for serving plugin files.
  • Flexibility: Easily customize your repository structure and access controls.
  • Low Overhead: Minimal resource usage makes it suitable for various hosting environments.

Features

  • Single-File Deployment: Redbean combines the web server and your content into a single executable file, simplifying deployment and distribution.
  • Automatic Download: The plugin manager can automatically download and set up the Redbean server.
  • Easy Repository Deployment: Deploy your plugin repository with a single function call.
  • Cross-Platform Compatibility: Redbean works on various platforms, including Linux, macOS, and Windows.
  • Lightweight: Redbean has a small footprint, making it ideal for plugin repositories of all sizes.

Step-by-Step Guide to Implementing and Deploying Redbean

Setup a Remote Repository

repo, err := manager.SetupRemoteRepository("[email protected]:/path/to/repo", "/path/to/ssh/key")

Prepare Local Directory for Deployment

Create a local directory to store your plugins and repository structure:

localRepoPath := "./repository"

Add Plugins to the Local Repository.

Copy or move your plugin files to the local repository directory.

Deploy the Repository

err = manager.DeployRepository(repo, localRepoPath)

This step will:

  • Download the latest version of Redbean (if not present)
  • Package your plugins and repository structure into a Redbean executable
  • Deploy the Redbean executable to your remote server (if a remote URL was provided)

Verify Deployment

If deployed remotely, SSH into your server and check that the Redbean executable is present and running:

ssh [email protected]
ls /path/to/repo/redbean.com
ps aux | grep redbean

Access Your Plugin Repository

Your plugins are now accessible via HTTP/HTTPS. If Redbean is running on the default port, you can access your plugins at: http://your-server-address:8080/plugins/

Update Repository

To update your repository, simply repeat steps 4-5. The plugin manager will handle updating the Redbean executable and redeploying your changes.

Advanced Configuration

When deploying your plugin repository via redbean, the plugin manager will include a redbean.ini file that you can use to customize your repository's server configuration.

[server]
port = 9000
addr = 127.0.0.1

Refer to the redbean.ini reference for a comprehensive list of commands.

Important

  • Always use HTTPS in production environments.
  • Implement proper access controls to restrict repository access.
  • Regularly update both your plugins and the Redbean executable to ensure you have the latest security patches.

API Reference

Management
  • NewManager(configPath string, pluginDir string, publicKeyPath string) (*Manager, error)
  • LoadPlugin(path string) error
  • UnloadPlugin(name string) error
  • ExecutePlugin(name string) error
  • HotReload(name string, path string) error
  • EnablePlugin(name string) error
  • DisablePlugin(name string) error
  • LoadEnabledPlugins(pluginDir string) error
  • ListPlugins() []string
  • GetPluginStats(name string) (*PluginStats, error)
  • SubscribeToEvent(eventName string, handler EventHandler)
Automatic Discovery and Updates
  • DiscoverPlugins(dir string) error
  • CheckForUpdates(repo *PluginRepository) ([]string, error)
  • UpdatePlugin(repo *PluginRepository, pluginName string) error
Remote Repository (via redbean)
  • SetupRemoteRepository(url, sshKeyPath string) (*PluginRepository, error)
  • DeployRepository(repo *PluginRepository, localPath string) error
EventBus
  • Subscribe(eventName string, handler EventHandler)
  • Publish(event Event)
Sandbox
  • Enable() error
  • Disable() error
  • VerifyPluginPath(path string) error

License

This project is licensed under the MIT License - see the LICENSE file for details.

plugin-manager's People

Contributors

matt-dunleavy avatar

Stargazers

 avatar  avatar

Watchers

 avatar

plugin-manager's Issues

New features added

Each plugin module may also have additional dynamic configuration options. Do you have any plans to add a method for dynamically setting plugin parameters?

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.