105 lines
2.4 KiB
Go
105 lines
2.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"sort"
|
|
"sync"
|
|
|
|
"github.com/letsencrypt/validator/v10"
|
|
)
|
|
|
|
type ConfigValidator struct {
|
|
Config interface{}
|
|
Validators map[string]validator.Func
|
|
}
|
|
|
|
var registry struct {
|
|
sync.Mutex
|
|
commands map[string]func()
|
|
configs map[string]*ConfigValidator
|
|
}
|
|
|
|
// RegisterCommand registers a subcommand and its corresponding config
|
|
// validator. The provided func() is called when the subcommand is invoked on
|
|
// the command line. The ConfigValidator is optional and used to validate the
|
|
// config file for the subcommand.
|
|
func RegisterCommand(name string, f func(), cv *ConfigValidator) {
|
|
registry.Lock()
|
|
defer registry.Unlock()
|
|
|
|
if registry.commands == nil {
|
|
registry.commands = make(map[string]func())
|
|
}
|
|
|
|
if registry.commands[name] != nil {
|
|
panic(fmt.Sprintf("command %q was registered twice", name))
|
|
}
|
|
registry.commands[name] = f
|
|
|
|
if cv == nil {
|
|
return
|
|
}
|
|
|
|
if registry.configs == nil {
|
|
registry.configs = make(map[string]*ConfigValidator)
|
|
}
|
|
|
|
if registry.configs[name] != nil {
|
|
panic(fmt.Sprintf("config validator for command %q was registered twice", name))
|
|
}
|
|
registry.configs[name] = cv
|
|
}
|
|
|
|
func LookupCommand(name string) func() {
|
|
registry.Lock()
|
|
defer registry.Unlock()
|
|
return registry.commands[name]
|
|
}
|
|
|
|
func AvailableCommands() []string {
|
|
registry.Lock()
|
|
defer registry.Unlock()
|
|
var avail []string
|
|
for name := range registry.commands {
|
|
avail = append(avail, name)
|
|
}
|
|
sort.Strings(avail)
|
|
return avail
|
|
}
|
|
|
|
// LookupConfigValidator constructs an instance of the *ConfigValidator for the
|
|
// given Boulder component name. If no *ConfigValidator was registered, nil is
|
|
// returned.
|
|
func LookupConfigValidator(name string) *ConfigValidator {
|
|
registry.Lock()
|
|
defer registry.Unlock()
|
|
if registry.configs[name] == nil {
|
|
return nil
|
|
}
|
|
|
|
// Create a new copy of the config struct so that we can validate it
|
|
// multiple times without mutating the registry's copy.
|
|
copy := reflect.New(reflect.ValueOf(
|
|
registry.configs[name].Config).Elem().Type(),
|
|
).Interface()
|
|
|
|
return &ConfigValidator{
|
|
Config: copy,
|
|
Validators: registry.configs[name].Validators,
|
|
}
|
|
}
|
|
|
|
// AvailableConfigValidators returns a list of Boulder component names for which
|
|
// a *ConfigValidator has been registered.
|
|
func AvailableConfigValidators() []string {
|
|
registry.Lock()
|
|
defer registry.Unlock()
|
|
var avail []string
|
|
for name := range registry.configs {
|
|
avail = append(avail, name)
|
|
}
|
|
sort.Strings(avail)
|
|
return avail
|
|
}
|