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 }