package converter import ( "fmt" "sort" "github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/ingress/pkg/store" v1 "k8s.io/api/networking/v1" ) const ( HttpServer = "ingress_server" MetricsServer = "metrics_server" ) // GlobalMiddleware is called with a default caddy config // already configured with: // - Secret storage store // - A TLS App (https://caddyserver.com/docs/json/apps/tls/) // - A HTTP App with an HTTP server listening to 80 443 ports (https://caddyserver.com/docs/json/apps/http/) type GlobalMiddleware interface { GlobalHandler(config *Config, store *store.Store) error } type IngressMiddlewareInput struct { Config *Config Store *store.Store Ingress *v1.Ingress Rule v1.IngressRule Path v1.HTTPIngressPath Route *caddyhttp.Route } // IngressMiddleware is called for each Caddy route that is generated for a specific // ingress. It allows anyone to manipulate caddy routes before sending it to caddy. type IngressMiddleware interface { IngressHandler(input IngressMiddlewareInput) (*caddyhttp.Route, error) } type Plugin interface { IngressPlugin() PluginInfo } type PluginInfo struct { Name string Priority int New func() Plugin } func RegisterPlugin(m Plugin) { plugin := m.IngressPlugin() if _, ok := plugins[plugin.Name]; ok { panic(fmt.Sprintf("plugin already registered: %s", plugin.Name)) } plugins[plugin.Name] = plugin pluginInstances[plugin.Name] = plugin.New() } func getOrderIndex(order []string, plugin string) int { for idx, o := range order { if plugin == o { return idx } } return -1 } func sortPlugins(plugins []PluginInfo, order []string) []PluginInfo { sort.SliceStable(plugins, func(i, j int) bool { iPlugin, jPlugin := plugins[i], plugins[j] iSortedIdx := getOrderIndex(order, iPlugin.Name) jSortedIdx := getOrderIndex(order, jPlugin.Name) if iSortedIdx != jSortedIdx { return iSortedIdx > jSortedIdx } if iPlugin.Priority != jPlugin.Priority { return iPlugin.Priority > jPlugin.Priority } return iPlugin.Name < jPlugin.Name }) return plugins } // Plugins return a sorted array of plugin instances. // Sort is made following these rules: // - Plugins specified in the order slice will always go first (in the order specified in the slice) // - A Plugin with higher priority will go before a plugin with lower priority // - If 2 plugins have the same priority (and not in order slice), they will be sorted by plugin name func Plugins(order []string) []Plugin { sortedPlugins := make([]PluginInfo, 0, len(plugins)) for _, p := range plugins { sortedPlugins = append(sortedPlugins, p) } sortPlugins(sortedPlugins, order) pluginArr := make([]Plugin, 0, len(plugins)) for _, p := range sortedPlugins { pluginArr = append(pluginArr, pluginInstances[p.Name]) } return pluginArr } var ( plugins = make(map[string]PluginInfo) pluginInstances = make(map[string]Plugin) )