Load tests plugins
This commit is contained in:
parent
735c4f1c57
commit
6a68bafdbb
5 changed files with 160 additions and 0 deletions
|
|
@ -77,6 +77,8 @@ type App struct {
|
|||
router *gin.Engine
|
||||
srv *http.Server
|
||||
insights *insightsCollector
|
||||
plugins []happydns.TestPlugin
|
||||
pluginsIdx map[string]happydns.TestPlugin
|
||||
store storage.Storage
|
||||
usecases Usecases
|
||||
}
|
||||
|
|
@ -168,6 +170,7 @@ func NewApp(cfg *happydns.Options) *App {
|
|||
app.initInsights()
|
||||
app.initUsecases()
|
||||
app.setupRouter()
|
||||
app.LoadPlugins()
|
||||
|
||||
return app
|
||||
}
|
||||
|
|
@ -182,6 +185,7 @@ func NewAppWithStorage(cfg *happydns.Options, store storage.Storage) *App {
|
|||
app.initNewsletter()
|
||||
app.initUsecases()
|
||||
app.setupRouter()
|
||||
app.LoadPlugins()
|
||||
|
||||
return app
|
||||
}
|
||||
|
|
|
|||
95
internal/app/plugins.go
Normal file
95
internal/app/plugins.go
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"plugin"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func (a *App) LoadPlugins() error {
|
||||
a.pluginsIdx = map[string]happydns.TestPlugin{}
|
||||
|
||||
var ret error
|
||||
|
||||
for _, directory := range a.cfg.PluginsDirectories {
|
||||
files, err := os.ReadDir(directory)
|
||||
if err != nil {
|
||||
ret = errors.Join(ret, err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
fname := path.Join(directory, file.Name())
|
||||
|
||||
err = a.loadPlugin(fname)
|
||||
if err != nil {
|
||||
ret = errors.Join(ret, fmt.Errorf("unable to load plugin %q: %w", fname, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *App) loadPlugin(fname string) error {
|
||||
p, err := plugin.Open(fname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newplugin, err := p.Lookup("NewTestPlugin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
myplugin, err := newplugin.(func() (happydns.TestPlugin, error))()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.plugins = append(a.plugins, myplugin)
|
||||
|
||||
// Index the plugin by its names
|
||||
pluginNames := myplugin.PluginEnvName()
|
||||
for _, name := range pluginNames {
|
||||
if p, exists := a.pluginsIdx[name]; exists {
|
||||
log.Printf("Plugin name conflict: the plugin at %q tries to register the name %q but it's already registered by %q", fname, name, p.Version().Name)
|
||||
continue
|
||||
}
|
||||
|
||||
a.pluginsIdx[name] = myplugin
|
||||
}
|
||||
|
||||
log.Printf("Plugin %s loaded (version %s)", myplugin.Version().Name, myplugin.Version().Version)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -57,6 +57,8 @@ func declareFlags(o *happydns.Options) {
|
|||
flag.StringVar(&o.MailSMTPPassword, "mail-smtp-password", o.MailSMTPPassword, "Password associated with the given username for SMTP authentication")
|
||||
flag.BoolVar(&o.MailSMTPTLSSNoVerify, "mail-smtp-tls-no-verify", o.MailSMTPTLSSNoVerify, "Do not verify certificate validity on SMTP connection")
|
||||
|
||||
flag.Var(&ArrayArgs{&o.PluginsDirectories}, "plugins-directory", "Path to a directory containing plugins (can be repeated multiple times)")
|
||||
|
||||
// Others flags are declared in some other files likes sources, storages, ... when they need specials configurations
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ type Options struct {
|
|||
MailSMTPTLSSNoVerify bool
|
||||
|
||||
OIDCClients []OIDCSettings
|
||||
|
||||
PluginsDirectories []string
|
||||
}
|
||||
|
||||
// GetBaseURL returns the full url to the absolute ExternalURL, including BaseURL.
|
||||
|
|
|
|||
57
model/plugin.go
Normal file
57
model/plugin.go
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package happydns
|
||||
|
||||
const (
|
||||
PluginResultStatusKO PluginResultStatus = iota
|
||||
PluginResultStatusWarn
|
||||
PluginResultStatusInfo
|
||||
PluginResultStatusOK
|
||||
)
|
||||
|
||||
type PluginResultStatus int
|
||||
|
||||
type TestPlugin interface {
|
||||
PluginEnvName() []string
|
||||
Version() PluginVersionInfo
|
||||
|
||||
RunTest(options map[string]interface{}, meta map[string]string) (*PluginResult, error)
|
||||
}
|
||||
|
||||
type PluginVersionInfo struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
AvailableOn PluginAvailability `json:"availableOn"`
|
||||
}
|
||||
|
||||
type PluginAvailability struct {
|
||||
ApplyToDomain bool `json:"applyToDomain,omitempty"`
|
||||
ApplyToService bool `json:"applyToDomain,omitempty"`
|
||||
LimitToProviders []string `json:"limitToProviders,omitempty"`
|
||||
LimitToServices []string `json:"limitToServices,omitempty"`
|
||||
}
|
||||
|
||||
type PluginResult struct {
|
||||
Status PluginResultStatus `json:"status"`
|
||||
StatusLine string `json:"statusLine,omitempty"`
|
||||
Report interface{} `json:"report"`
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue