Updated documentation

This commit is contained in:
Matt Dunleavy
2024-07-06 18:44:59 -04:00
parent eedbbfec4a
commit fdc491362e
6 changed files with 305 additions and 77 deletions

382
README.md
View File

@@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 KiB

Binary file not shown.

BIN
assets/img/redbean.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB