100 lines
1.8 KiB
Go
100 lines
1.8 KiB
Go
package check
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
"code.icb4dc0.de/prskr/nurse/config"
|
|
"code.icb4dc0.de/prskr/nurse/grammar"
|
|
)
|
|
|
|
type (
|
|
ModuleOption interface {
|
|
Apply(m *Module) error
|
|
}
|
|
|
|
ModuleOptionFunc func(m *Module) error
|
|
|
|
Factory interface {
|
|
New() SystemChecker
|
|
}
|
|
|
|
FactoryFunc func() SystemChecker
|
|
)
|
|
|
|
func (f ModuleOptionFunc) Apply(m *Module) error {
|
|
return f(m)
|
|
}
|
|
|
|
//nolint:ireturn // required to implement interface
|
|
func (f FactoryFunc) New() SystemChecker {
|
|
return f()
|
|
}
|
|
|
|
//nolint:ireturn // required to implement interface
|
|
func WithCheck(name string, factory Factory) ModuleOption {
|
|
return ModuleOptionFunc(func(m *Module) error {
|
|
return m.Register(name, factory)
|
|
})
|
|
}
|
|
|
|
func NewModule(name string, opts ...ModuleOption) (*Module, error) {
|
|
m := &Module{
|
|
name: name,
|
|
knownChecks: make(map[string]Factory),
|
|
}
|
|
|
|
for i := range opts {
|
|
if err := opts[i].Apply(m); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
type Module struct {
|
|
name string
|
|
lock sync.RWMutex
|
|
knownChecks map[string]Factory
|
|
}
|
|
|
|
func (m *Module) Name() string {
|
|
return m.name
|
|
}
|
|
|
|
//nolint:ireturn // required to implement interface
|
|
func (m *Module) Lookup(c grammar.Check, srvLookup config.ServerLookup) (SystemChecker, error) {
|
|
m.lock.RLock()
|
|
defer m.lock.RUnlock()
|
|
var (
|
|
factory Factory
|
|
ok bool
|
|
)
|
|
if factory, ok = m.knownChecks[strings.ToLower(c.Initiator.Name)]; !ok {
|
|
return nil, fmt.Errorf("%w: %s", ErrNoSuchCheck, c.Initiator.Name)
|
|
}
|
|
|
|
chk := factory.New()
|
|
if err := chk.UnmarshalCheck(c, srvLookup); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return chk, nil
|
|
}
|
|
|
|
func (m *Module) Register(name string, factory Factory) error {
|
|
m.lock.Lock()
|
|
defer m.lock.Unlock()
|
|
|
|
name = strings.ToLower(name)
|
|
|
|
if _, ok := m.knownChecks[name]; ok {
|
|
return fmt.Errorf("%w: %s", ErrConflictingCheck, name)
|
|
}
|
|
|
|
m.knownChecks[name] = factory
|
|
|
|
return nil
|
|
}
|