feat(plugin): enforce api version compatibility at registration
This commit is contained in:
parent
5680f69e8b
commit
f84f55f80f
4 changed files with 40 additions and 1 deletions
|
|
@ -17,6 +17,10 @@ func (p blockingPlugin) Name() string {
|
||||||
return "block-outbound"
|
return "block-outbound"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p blockingPlugin) APIVersion() string {
|
||||||
|
return plugin.APIVersion
|
||||||
|
}
|
||||||
|
|
||||||
func (p blockingPlugin) Register(r *hooks.HookRegistry) error {
|
func (p blockingPlugin) Register(r *hooks.HookRegistry) error {
|
||||||
r.OnMessageSending("block-all", 0, func(_ context.Context, e *hooks.MessageSendingEvent) error {
|
r.OnMessageSending("block-all", 0, func(_ context.Context, e *hooks.MessageSendingEvent) error {
|
||||||
e.Cancel = true
|
e.Cancel = true
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/pkg/hooks"
|
"github.com/sipeed/picoclaw/pkg/hooks"
|
||||||
|
"github.com/sipeed/picoclaw/pkg/plugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PolicyDemoConfig controls the demo plugin behavior.
|
// PolicyDemoConfig controls the demo plugin behavior.
|
||||||
|
|
@ -108,6 +109,10 @@ func (p *PolicyDemoPlugin) Name() string {
|
||||||
return "policy-demo"
|
return "policy-demo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PolicyDemoPlugin) APIVersion() string {
|
||||||
|
return plugin.APIVersion
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PolicyDemoPlugin) Snapshot() PolicyDemoStats {
|
func (p *PolicyDemoPlugin) Snapshot() PolicyDemoStats {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ const APIVersion = "v1alpha1"
|
||||||
// Plugin is the Phase-1 compile-time contract for PicoClaw extensions.
|
// Plugin is the Phase-1 compile-time contract for PicoClaw extensions.
|
||||||
type Plugin interface {
|
type Plugin interface {
|
||||||
Name() string
|
Name() string
|
||||||
|
APIVersion() string
|
||||||
Register(*hooks.HookRegistry) error
|
Register(*hooks.HookRegistry) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,6 +63,17 @@ func (m *Manager) Register(p Plugin) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return errors.New("plugin name is required")
|
return errors.New("plugin name is required")
|
||||||
}
|
}
|
||||||
|
if got := strings.TrimSpace(p.APIVersion()); got != APIVersion {
|
||||||
|
if got == "" {
|
||||||
|
got = "<empty>"
|
||||||
|
}
|
||||||
|
return fmt.Errorf(
|
||||||
|
"plugin %q api version mismatch: got %s, want %s",
|
||||||
|
name,
|
||||||
|
got,
|
||||||
|
APIVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
@ -85,4 +97,3 @@ func (m *Manager) RegisterAll(plugins ...Plugin) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
type testPlugin struct {
|
type testPlugin struct {
|
||||||
name string
|
name string
|
||||||
|
apiVersion string
|
||||||
registerFn func(*hooks.HookRegistry) error
|
registerFn func(*hooks.HookRegistry) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,6 +25,13 @@ func (p testPlugin) Register(r *hooks.HookRegistry) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p testPlugin) APIVersion() string {
|
||||||
|
if p.apiVersion == "" {
|
||||||
|
return APIVersion
|
||||||
|
}
|
||||||
|
return p.apiVersion
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewManager(t *testing.T) {
|
func TestNewManager(t *testing.T) {
|
||||||
m := NewManager()
|
m := NewManager()
|
||||||
if m == nil {
|
if m == nil {
|
||||||
|
|
@ -110,3 +118,14 @@ func TestRegisterPropagatesPluginError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRegisterRejectsPluginVersionMismatch(t *testing.T) {
|
||||||
|
m := NewManager()
|
||||||
|
p := testPlugin{
|
||||||
|
name: "old-plugin",
|
||||||
|
apiVersion: "v0",
|
||||||
|
}
|
||||||
|
err := m.Register(p)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected version mismatch error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue