mirror of
https://github.com/matt-dunleavy/plugin-manager.git
synced 2025-09-27 01:36:01 +08:00
Updated documentation
This commit is contained in:
382
README.md
382
README.md
@@ -1,37 +1,171 @@
|
||||
# Plugin Manager for Go
|
||||
# <img src="assets/img/plugin-manager-go-256.png" style="float:right"/>Plugin Manager for Go
|
||||
|
||||
A flexible and robust plugin management library for Go applications.
|
||||
A robust plugin management library for Go applications.
|
||||
|
||||
## Features
|
||||
##### Features
|
||||
|
||||
- Dynamic loading and unloading of plugins
|
||||
- Plugin versioning and dependency management
|
||||
- Hot-reloading of plugins
|
||||
- Event system for plugin lifecycle events
|
||||
- Basic sandboxing for improved security
|
||||
- Metrics collection for plugin performance
|
||||
- Dynamic Loading and Unloading
|
||||
- Versioning and Dependency Management
|
||||
- Hot-Reloading and Lazy Loading
|
||||
- Event System for Lifecycle Events
|
||||
- Enhanced Sandboxing for improved security
|
||||
|
||||
## Installation
|
||||
- Metrics Collection for Plugin Performance
|
||||
|
||||
To use this plugin manager in your Go project, run:
|
||||
##### 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):
|
||||
|
||||
```bash
|
||||
go get github.com/matt-dunleavy/plugin-manager
|
||||
```
|
||||
|
||||
## Installation
|
||||
Or clone the repository to your local machine using the Git Command Line by running the following command in your terminal:
|
||||
|
||||
To use this plugin manager in your Go project, run:
|
||||
```sh
|
||||
git clone https://github.com/matt-dunleavy/plugin-manager.git
|
||||
cd plugin-manager
|
||||
```
|
||||
|
||||
```bash
|
||||
go get github.com/matt-dunleavy/plugin-manager
|
||||
After you've obtained the library, import the package into your source code:
|
||||
|
||||
```go
|
||||
import "github.com/matt-dunleavy/plugin-manager"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Creating a plugin
|
||||
Visit to the [examples]() directory for full-featured implementations.
|
||||
|
||||
Plugins must implement the `Plugin` interface:
|
||||
#### Initialize a New Plugin Manager
|
||||
|
||||
Create a new plugin manager instance at the start of your application.
|
||||
|
||||
```go
|
||||
manager, err := pm.NewManager("plugins.json", "./plugins", "public_key.pem")
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
|
||||
- `configPath` (string): Path to the JSON configuration file for managing enabled/disabled plugins.
|
||||
- `pluginDir` (string): Directory where plugins are stored.
|
||||
- `publicKeyPath` (string): Path to the public key file used for verifying plugin signatures.
|
||||
|
||||
**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.
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
```go
|
||||
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).
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
```go
|
||||
package main
|
||||
@@ -47,20 +181,35 @@ func (p *MyPlugin) Metadata() pm.PluginMetadata {
|
||||
return pm.PluginMetadata{
|
||||
Name: "MyPlugin",
|
||||
Version: "1.0.0",
|
||||
Dependencies: []string{},
|
||||
Dependencies: map[string]string{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *MyPlugin) PreLoad() error {
|
||||
fmt.Println("MyPlugin pre-load")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MyPlugin) Init() error {
|
||||
fmt.Println("MyPlugin initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MyPlugin) PostLoad() error {
|
||||
fmt.Println("MyPlugin post-load")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MyPlugin) Execute() error {
|
||||
fmt.Println("MyPlugin executed")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MyPlugin) PreUnload() error {
|
||||
fmt.Println("MyPlugin pre-unload")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *MyPlugin) Shutdown() error {
|
||||
fmt.Println("MyPlugin shut down")
|
||||
return nil
|
||||
@@ -69,64 +218,25 @@ func (p *MyPlugin) Shutdown() error {
|
||||
var Plugin MyPlugin
|
||||
```
|
||||
|
||||
### Compiling Plugins
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Each of these methods should return an error if something goes wrong during their execution. Returning `nil` indicates successful completion.
|
||||
|
||||
Compile your plugin with:
|
||||
> [!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 your plugin with the standard Go toolchain by setting the `-buildmode` flag to `plugin`:
|
||||
|
||||
```bash
|
||||
go build -buildmode=plugin -o myplugin.so myplugin.go
|
||||
```
|
||||
|
||||
### Using the Plugin Manager
|
||||
|
||||
Here's an example of how to use the plugin manager in your application:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
pm "github.com/matt-dunleavy/plugin-manager"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create a new plugin manager
|
||||
manager, err := pm.NewManager("plugins.json", "./plugins")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create plugin manager: %v", err)
|
||||
}
|
||||
|
||||
// Load a plugin
|
||||
err = manager.LoadPlugin("./plugins/myplugin.so")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load plugin: %v", err)
|
||||
}
|
||||
|
||||
// Execute a plugin
|
||||
err = manager.ExecutePlugin("MyPlugin")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to execute plugin: %v", err)
|
||||
}
|
||||
|
||||
// Hot-reload a plugin
|
||||
err = manager.HotReload("MyPlugin", "./plugins/myplugin_v2.so")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to hot-reload plugin: %v", err)
|
||||
}
|
||||
|
||||
// Unload a plugin
|
||||
err = manager.UnloadPlugin("MyPlugin")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to unload plugin: %v", err)
|
||||
}
|
||||
|
||||
// Subscribe to plugin events
|
||||
manager.SubscribeToEvent("PluginLoaded", func(e pm.Event) {
|
||||
fmt.Printf("Plugin loaded: %s\n", e.(pm.PluginLoadedEvent).PluginName)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -141,11 +251,122 @@ The plugin manager uses a JSON configuration file to keep track of enabled plugi
|
||||
}
|
||||
```
|
||||
|
||||
## Simplified Deployment Plugin Repositories
|
||||
|
||||
<img src="assets/img/redbean.png" style="float:right"/>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
|
||||
|
||||
1. ##### **Initialize the Plugin Manager**
|
||||
|
||||
```go
|
||||
manager, err := pm.NewManager("plugins.json", "./plugins", "public_key.pem")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create plugin manager: %v", err)
|
||||
}
|
||||
```
|
||||
|
||||
2. ##### **Setup the Remote Repository**
|
||||
|
||||
```go
|
||||
repo, err := manager.SetupRemoteRepository("user@example.com:/path/to/repo", "/path/to/ssh/key")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to setup remote repository: %v", err)
|
||||
}
|
||||
```
|
||||
|
||||
3. ##### **Prepare Local Directory for Deployment**.
|
||||
|
||||
Create a local directory to store your plugins and repository structure:
|
||||
|
||||
```go
|
||||
localRepoPath := "./repository"
|
||||
if err := os.MkdirAll(localRepoPath, 0755); err != nil {
|
||||
log.Fatalf("Failed to create local repository directory: %v", err)
|
||||
}
|
||||
```
|
||||
|
||||
4. ##### **Add Plugins to the Local Repository.**
|
||||
|
||||
Copy or move your plugin files to the local repository directory.
|
||||
|
||||
5. ##### **Deploy the Repository**
|
||||
|
||||
```go
|
||||
err = manager.DeployRepository(repo, localRepoPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to deploy repository: %v", err)
|
||||
}
|
||||
```
|
||||
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)
|
||||
|
||||
6. ##### **Verify Deployment**
|
||||
|
||||
If deployed remotely, SSH into your server and check that the Redbean executable is present and running:
|
||||
|
||||
```bash
|
||||
ssh user@example.com
|
||||
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
|
||||
|
||||
Redbean offers various configuration options. You can create a `redbean.ini` file in your local repository directory to customize settings:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
port = 9000
|
||||
addr = 127.0.0.1
|
||||
```
|
||||
|
||||
The plugin manager will include this configuration when deploying your repository.
|
||||
|
||||
> [!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
|
||||
|
||||
### Manager
|
||||
##### Management
|
||||
|
||||
- `NewManager(configPath string, pluginDir string) (*Manager, error)`
|
||||
- `NewManager(configPath string, pluginDir string, publicKeyPath string) (*Manager, error)`
|
||||
- `LoadPlugin(path string) error`
|
||||
- `UnloadPlugin(name string) error`
|
||||
- `ExecutePlugin(name string) error`
|
||||
@@ -157,21 +378,28 @@ The plugin manager uses a JSON configuration file to keep track of enabled plugi
|
||||
- `GetPluginStats(name string) (*PluginStats, error)`
|
||||
- `SubscribeToEvent(eventName string, handler EventHandler)`
|
||||
|
||||
### EventBus
|
||||
##### Automatic Discovery and Updates
|
||||
|
||||
- `DiscoverPlugins(dir string) error`
|
||||
- `CheckForUpdates(repo *PluginRepository) ([]string, error)`
|
||||
- `UpdatePlugin(repo *PluginRepository, pluginName string) error`
|
||||
|
||||
##### Remote Repository (via [redbean](https://redbean.dev/))
|
||||
|
||||
- `SetupRemoteRepository(url, sshKeyPath string) (*PluginRepository, error)`
|
||||
- `DeployRepository(repo *PluginRepository, localPath string) error`
|
||||
|
||||
##### EventBus
|
||||
|
||||
- `Subscribe(eventName string, handler EventHandler)`
|
||||
- `Publish(event Event)`
|
||||
|
||||
### Sandbox
|
||||
##### Sandbox
|
||||
|
||||
- `Enable() error`
|
||||
- `Disable() error`
|
||||
- `VerifyPluginPath(path string) error`
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
BIN
assets/img/plugin-manager-go-256.png
Normal file
BIN
assets/img/plugin-manager-go-256.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
BIN
assets/img/plugin-manager-go-512.png
Normal file
BIN
assets/img/plugin-manager-go-512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
BIN
assets/img/plugin-manager-go.png
Normal file
BIN
assets/img/plugin-manager-go.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 761 KiB |
BIN
assets/img/plugin-manager-go.png-autosave.kra
Normal file
BIN
assets/img/plugin-manager-go.png-autosave.kra
Normal file
Binary file not shown.
BIN
assets/img/redbean.png
Normal file
BIN
assets/img/redbean.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
Reference in New Issue
Block a user