306 lines
8.3 KiB
Go
306 lines
8.3 KiB
Go
package plugins
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
pluginv1 "github.com/Silo-Server/silo-plugin-sdk/pkg/pluginproto/silo/plugin/v1"
|
|
)
|
|
|
|
type fakeServiceConfigStore struct {
|
|
configsByInstallation map[int][]*RuntimeConfig
|
|
puts []putGlobalConfigCall
|
|
putErr error
|
|
}
|
|
|
|
type putGlobalConfigCall struct {
|
|
installationID int
|
|
key string
|
|
value map[string]any
|
|
}
|
|
|
|
func (f *fakeServiceConfigStore) ListGlobalConfigs(
|
|
_ context.Context,
|
|
installationID int,
|
|
) ([]*RuntimeConfig, error) {
|
|
configs := f.configsByInstallation[installationID]
|
|
result := make([]*RuntimeConfig, 0, len(configs))
|
|
for _, config := range configs {
|
|
if config == nil {
|
|
continue
|
|
}
|
|
cloned := *config
|
|
cloned.Value = cloneConfigMap(config.Value)
|
|
result = append(result, &cloned)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (f *fakeServiceConfigStore) PutGlobalConfig(
|
|
_ context.Context,
|
|
installationID int,
|
|
key string,
|
|
value map[string]any,
|
|
) error {
|
|
f.puts = append(f.puts, putGlobalConfigCall{
|
|
installationID: installationID,
|
|
key: key,
|
|
value: cloneConfigMap(value),
|
|
})
|
|
return f.putErr
|
|
}
|
|
|
|
func TestServiceTestGlobalConfigUsesMergedDraftAndStopsTemporaryInstance(t *testing.T) {
|
|
originalProbe := runPluginConnectionCheck
|
|
t.Cleanup(func() {
|
|
runPluginConnectionCheck = originalProbe
|
|
})
|
|
|
|
probeCalls := 0
|
|
runPluginConnectionCheck = func(
|
|
_ context.Context,
|
|
client pluginClient,
|
|
manifest *pluginv1.PluginManifest,
|
|
) error {
|
|
probeCalls++
|
|
if client == nil {
|
|
t.Fatal("probe client = nil, want started client")
|
|
}
|
|
if manifest.GetPluginId() != "silo.metadb" {
|
|
t.Fatalf("manifest plugin id = %q, want silo.metadb", manifest.GetPluginId())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
manifest := connectionTestManifest(t, "silo.metadb", "0.0.36")
|
|
installPath := writeInstalledPluginManifest(t, manifest)
|
|
host := &fakeServiceHost{
|
|
startResult: &fakePluginClient{manifest: manifest},
|
|
}
|
|
service := &Service{
|
|
installations: newFakeServiceInstallationStore(&Installation{
|
|
ID: 42,
|
|
PluginID: manifest.GetPluginId(),
|
|
Version: manifest.GetVersion(),
|
|
InstallPath: installPath,
|
|
Enabled: false,
|
|
}),
|
|
configs: &fakeServiceConfigStore{
|
|
configsByInstallation: map[int][]*RuntimeConfig{
|
|
42: {
|
|
{
|
|
InstallationID: 42,
|
|
Key: "connection",
|
|
Value: map[string]any{
|
|
"api_key": "persisted",
|
|
},
|
|
},
|
|
{
|
|
InstallationID: 42,
|
|
Key: "secondary",
|
|
Value: map[string]any{
|
|
"enabled": true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
host: host,
|
|
}
|
|
|
|
if err := service.TestGlobalConfig(context.Background(), 42, "connection", map[string]any{
|
|
"api_key": "draft",
|
|
}); err != nil {
|
|
t.Fatalf("TestGlobalConfig() returned error: %v", err)
|
|
}
|
|
|
|
if probeCalls != 1 {
|
|
t.Fatalf("probe calls = %d, want 1", probeCalls)
|
|
}
|
|
if len(host.started) != 1 {
|
|
t.Fatalf("start calls = %d, want 1", len(host.started))
|
|
}
|
|
if len(host.stopped) != 1 {
|
|
t.Fatalf("stop calls = %d, want 1", len(host.stopped))
|
|
}
|
|
|
|
startReq := host.started[0]
|
|
if startReq.InstallationID >= 0 {
|
|
t.Fatalf("temporary installation id = %d, want negative id", startReq.InstallationID)
|
|
}
|
|
if host.stopped[0] != startReq.InstallationID {
|
|
t.Fatalf("stopped installation id = %d, want %d", host.stopped[0], startReq.InstallationID)
|
|
}
|
|
if len(startReq.Config) != 2 {
|
|
t.Fatalf("config entries = %d, want 2", len(startReq.Config))
|
|
}
|
|
|
|
valuesByKey := make(map[string]map[string]any, len(startReq.Config))
|
|
for _, entry := range startReq.Config {
|
|
valuesByKey[entry.GetKey()] = entry.GetValue().AsMap()
|
|
}
|
|
if got := valuesByKey["connection"]["api_key"]; got != "draft" {
|
|
t.Fatalf("connection api_key = %#v, want draft", got)
|
|
}
|
|
if got := valuesByKey["secondary"]["enabled"]; got != true {
|
|
t.Fatalf("secondary enabled = %#v, want true", got)
|
|
}
|
|
}
|
|
|
|
func TestServiceTestGlobalConfigReturnsUnsupportedWithoutStartingPlugin(t *testing.T) {
|
|
manifest := connectionTestManifest(t, "silo.simple", "0.0.1")
|
|
manifest.Capabilities = []*pluginv1.CapabilityDescriptor{
|
|
{
|
|
Type: "scheduled_task.v1",
|
|
Id: "refresh",
|
|
DisplayName: "Refresh",
|
|
},
|
|
}
|
|
installPath := writeInstalledPluginManifest(t, manifest)
|
|
host := &fakeServiceHost{}
|
|
service := &Service{
|
|
installations: newFakeServiceInstallationStore(&Installation{
|
|
ID: 7,
|
|
PluginID: manifest.GetPluginId(),
|
|
Version: manifest.GetVersion(),
|
|
InstallPath: installPath,
|
|
Enabled: true,
|
|
}),
|
|
host: host,
|
|
}
|
|
|
|
err := service.TestGlobalConfig(context.Background(), 7, "connection", map[string]any{
|
|
"api_key": "draft",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("TestGlobalConfig() returned nil error, want unsupported error")
|
|
}
|
|
|
|
var connectionErr *ConnectionTestError
|
|
if !errors.As(err, &connectionErr) {
|
|
t.Fatalf("error = %v, want ConnectionTestError", err)
|
|
}
|
|
if !strings.Contains(connectionErr.Error(), "not supported") {
|
|
t.Fatalf("connection error message = %q, want unsupported message", connectionErr.Error())
|
|
}
|
|
if len(host.started) != 0 {
|
|
t.Fatalf("start calls = %d, want 0", len(host.started))
|
|
}
|
|
if len(host.stopped) != 0 {
|
|
t.Fatalf("stop calls = %d, want 0", len(host.stopped))
|
|
}
|
|
}
|
|
|
|
func TestServiceTestGlobalConfigStopsTemporaryInstanceOnProbeFailure(t *testing.T) {
|
|
originalProbe := runPluginConnectionCheck
|
|
t.Cleanup(func() {
|
|
runPluginConnectionCheck = originalProbe
|
|
})
|
|
|
|
runPluginConnectionCheck = func(
|
|
_ context.Context,
|
|
_ pluginClient,
|
|
_ *pluginv1.PluginManifest,
|
|
) error {
|
|
return &ConnectionTestError{Message: "probe failed"}
|
|
}
|
|
|
|
manifest := connectionTestManifest(t, "silo.metadb", "0.0.36")
|
|
installPath := writeInstalledPluginManifest(t, manifest)
|
|
host := &fakeServiceHost{
|
|
startResult: &fakePluginClient{manifest: manifest},
|
|
}
|
|
service := &Service{
|
|
installations: newFakeServiceInstallationStore(&Installation{
|
|
ID: 19,
|
|
PluginID: manifest.GetPluginId(),
|
|
Version: manifest.GetVersion(),
|
|
InstallPath: installPath,
|
|
Enabled: true,
|
|
}),
|
|
host: host,
|
|
}
|
|
|
|
err := service.TestGlobalConfig(context.Background(), 19, "connection", map[string]any{
|
|
"api_key": "draft",
|
|
})
|
|
if err == nil {
|
|
t.Fatal("TestGlobalConfig() returned nil error, want probe failure")
|
|
}
|
|
if len(host.started) != 1 {
|
|
t.Fatalf("start calls = %d, want 1", len(host.started))
|
|
}
|
|
if len(host.stopped) != 1 {
|
|
t.Fatalf("stop calls = %d, want 1", len(host.stopped))
|
|
}
|
|
if host.stopped[0] != host.started[0].InstallationID {
|
|
t.Fatalf("stopped installation id = %d, want %d", host.stopped[0], host.started[0].InstallationID)
|
|
}
|
|
}
|
|
|
|
func TestServiceTestGlobalConfigUsesUniqueTemporaryInstallationIDs(t *testing.T) {
|
|
originalProbe := runPluginConnectionCheck
|
|
t.Cleanup(func() {
|
|
runPluginConnectionCheck = originalProbe
|
|
})
|
|
|
|
runPluginConnectionCheck = func(
|
|
_ context.Context,
|
|
_ pluginClient,
|
|
_ *pluginv1.PluginManifest,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
manifest := connectionTestManifest(t, "silo.metadb", "0.0.36")
|
|
installPath := writeInstalledPluginManifest(t, manifest)
|
|
host := &fakeServiceHost{
|
|
startResult: &fakePluginClient{manifest: manifest},
|
|
}
|
|
service := &Service{
|
|
installations: newFakeServiceInstallationStore(&Installation{
|
|
ID: 5,
|
|
PluginID: manifest.GetPluginId(),
|
|
Version: manifest.GetVersion(),
|
|
InstallPath: installPath,
|
|
Enabled: true,
|
|
}),
|
|
host: host,
|
|
}
|
|
|
|
if err := service.TestGlobalConfig(context.Background(), 5, "connection", map[string]any{
|
|
"api_key": "first",
|
|
}); err != nil {
|
|
t.Fatalf("first TestGlobalConfig() returned error: %v", err)
|
|
}
|
|
if err := service.TestGlobalConfig(context.Background(), 5, "connection", map[string]any{
|
|
"api_key": "second",
|
|
}); err != nil {
|
|
t.Fatalf("second TestGlobalConfig() returned error: %v", err)
|
|
}
|
|
|
|
if len(host.started) != 2 {
|
|
t.Fatalf("start calls = %d, want 2", len(host.started))
|
|
}
|
|
if host.started[0].InstallationID == host.started[1].InstallationID {
|
|
t.Fatalf("temporary installation ids matched: %d", host.started[0].InstallationID)
|
|
}
|
|
}
|
|
|
|
func connectionTestManifest(t *testing.T, pluginID, version string) *pluginv1.PluginManifest {
|
|
t.Helper()
|
|
|
|
manifest := testPluginManifest(t, pluginID, version)
|
|
manifest.GlobalConfigSchema = []*pluginv1.ConfigSchema{
|
|
{
|
|
Key: "connection",
|
|
Title: "Connection",
|
|
Required: true,
|
|
JsonSchema: `{"type":"object","properties":{"api_key":{"type":"string"}},"required":["api_key"],"additionalProperties":false}`,
|
|
},
|
|
}
|
|
return manifest
|
|
}
|