caddy-ingess/internal/k8s/configmap.go
Marc-Antoine e9c594cd55
feat(annotations): Add annotations to rewrite requests (#68)
* feat(annotations): Add annotations to rewrite requests

* Upgrade caddy, ingress API version and some other deps

* fix graceful shutdown

* Upgrade caddy to v2.4.6 and add OCSP Check interval to global config

* Add caddy duration parser
2022-03-26 23:19:04 -06:00

111 lines
3.2 KiB
Go

package k8s
import (
"github.com/caddyserver/caddy/v2"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
v12 "k8s.io/api/core/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"reflect"
"time"
)
// ConfigMapOptions represents global options set through a configmap
type ConfigMapOptions struct {
Debug bool `json:"debug,omitempty"`
AcmeCA string `json:"acmeCA,omitempty"`
Email string `json:"email,omitempty"`
ProxyProtocol bool `json:"proxyProtocol,omitempty"`
Metrics bool `json:"metrics,omitempty"`
OnDemandTLS bool `json:"onDemandTLS,omitempty"`
OnDemandRateLimitInterval caddy.Duration `json:"onDemandTLSRateLimitInterval,omitempty"`
OnDemandRateLimitBurst int `json:"onDemandTLSRateLimitBurst,omitempty"`
OnDemandAsk string `json:"onDemandTLSAsk,omitempty"`
OCSPCheckInterval caddy.Duration `json:"ocspCheckInterval,omitempty"`
}
type ConfigMapHandlers struct {
AddFunc func(obj *v12.ConfigMap)
UpdateFunc func(oldObj, newObj *v12.ConfigMap)
DeleteFunc func(obj *v12.ConfigMap)
}
type ConfigMapParams struct {
Namespace string
InformerFactory informers.SharedInformerFactory
ConfigMapName string
}
func isControllerConfigMap(cm *v12.ConfigMap, name string) bool {
return cm.GetName() == name
}
func WatchConfigMaps(options ConfigMapParams, funcs ConfigMapHandlers) cache.SharedIndexInformer {
informer := options.InformerFactory.Core().V1().ConfigMaps().Informer()
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
cm, ok := obj.(*v12.ConfigMap)
if ok && isControllerConfigMap(cm, options.ConfigMapName) {
funcs.AddFunc(cm)
}
},
UpdateFunc: func(oldObj, newObj interface{}) {
oldCM, ok1 := oldObj.(*v12.ConfigMap)
newCM, ok2 := newObj.(*v12.ConfigMap)
if ok1 && ok2 && isControllerConfigMap(newCM, options.ConfigMapName) {
funcs.UpdateFunc(oldCM, newCM)
}
},
DeleteFunc: func(obj interface{}) {
cm, ok := obj.(*v12.ConfigMap)
if ok && isControllerConfigMap(cm, options.ConfigMapName) {
funcs.DeleteFunc(cm)
}
},
})
return informer
}
func stringToCaddyDurationHookFunc() mapstructure.DecodeHookFunc {
return func(f reflect.Type, t reflect.Type, data interface{}) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}
if t != reflect.TypeOf(caddy.Duration(time.Second)) {
return data, nil
}
return caddy.ParseDuration(data.(string))
}
}
func ParseConfigMap(cm *v12.ConfigMap) (*ConfigMapOptions, error) {
// parse configmap
cfgMap := ConfigMapOptions{}
config := &mapstructure.DecoderConfig{
Metadata: nil,
WeaklyTypedInput: true,
Result: &cfgMap,
TagName: "json",
DecodeHook: mapstructure.ComposeDecodeHookFunc(
stringToCaddyDurationHookFunc(),
),
}
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
return nil, errors.Wrap(err, "unexpected error creating decoder")
}
err = decoder.Decode(cm.Data)
if err != nil {
return nil, errors.Wrap(err, "unexpected error parsing configmap")
}
return &cfgMap, nil
}