114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
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)
|
|
)
|