Files
ipasso/backend/registration.go

105 lines
2.3 KiB
Go

package backend
import (
"flag"
"fmt"
"git.thequux.com/thequux/ipasso/util/startup"
"go.uber.org/zap"
"net/url"
"os"
"sort"
"strings"
)
var backendUrl = flag.String("backend", "help://", "URL of backend. Use help:// for a list, or help://[backend] for details on a particular backend")
var SessionStore Backend
type backendRecord struct {
description string
help string
factory Factory
}
// Factory for backend objects. You don't need this unless you're working on
// initialization machinery or implementing a backend
type Factory func(url *url.URL) (Backend, error)
var sessionLogger *zap.Logger
var registry = make(map[string]backendRecord)
func RegisterBackendFactory(scheme string, description string, help string, factory Factory) {
scheme = strings.ToLower(scheme)
_, exist := registry[scheme]
if exist {
panic("Scheme " + scheme + " registered multiple times")
}
registry[scheme] = backendRecord{
description: description,
help: help,
factory: factory,
}
}
func init() {
// register the help factory
RegisterBackendFactory("help", "Help on backends", `
Usage:
help:// List available backends
help://backend Print help on a specific backend
`,
backendHelp,
)
startup.Logger.Add(func() {
sessionLogger = zap.L().Named("session")
})
startup.PostFlags.Add(func() {
parsed, err := url.Parse(*backendUrl)
if err != nil {
sessionLogger.Fatal("Invalid backend spec", zap.Error(err))
}
backend, ok := registry[parsed.Scheme]
if !ok {
sessionLogger.Fatal("Unknown backend type", zap.String("scheme", parsed.Scheme))
}
SessionStore, err = backend.factory(parsed)
if err != nil {
sessionLogger.Fatal("Failed to initialize backend", zap.Error(err))
}
})
}
func backendHelp(url *url.URL) (Backend, error) {
scheme := url.Hostname()
if scheme != "" {
backend, ok := registry[scheme]
if ok {
fmt.Println(strings.TrimPrefix(backend.help, "\n"))
os.Exit(1)
}
}
var backendList []string
var maxLen = 0
for name := range registry {
backendList = append(backendList, name)
if len(name) > maxLen {
maxLen = len(name)
}
}
sort.Strings(backendList)
fmt.Println("Available backends:")
for _, name := range backendList {
fmt.Printf("%*s %s\n", maxLen, name, registry[name].description)
}
os.Exit(1)
return nil, nil
}