The chain middleware in k8s use middlewareRef

This commit is contained in:
Julien Salleyron 2019-09-03 19:20:04 +02:00 committed by Traefiker Bot
parent 261e7c1744
commit 770b3739e0
6 changed files with 269 additions and 21 deletions

View file

@ -51,9 +51,9 @@ metadata:
spec:
chain:
middlewares:
- https-only
- known-ips
- auth-users
- name: https-only
- name: known-ips
- name: auth-users
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware

View file

@ -1,5 +1,17 @@
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: mychain
namespace: default
spec:
chain:
middlewares:
- name: stripprefix
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: stripprefix
namespace: default
@ -26,4 +38,4 @@ spec:
- name: whoami
port: 80
middlewares:
- name: stripprefix
- name: mychain

View file

@ -20,7 +20,7 @@
"web"
],
"middlewares": [
"default/stripprefix"
"default/mychain"
],
"service": "default/test2.route-23c7f4c450289ee29016",
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/tobestripped`)",
@ -31,16 +31,24 @@
}
},
"middlewares": {
"default/stripprefix@kubernetescrd": {
"stripPrefix": {
"prefixes": [
"/tobestripped"
"default/mychain@kubernetescrd": {
"chain": {
"middlewares": [
"default/stripprefix"
]
},
"status": "enabled",
"usedBy": [
"default/test2.route-23c7f4c450289ee29016@kubernetescrd"
]
},
"default/stripprefix@kubernetescrd": {
"stripPrefix": {
"prefixes": [
"/tobestripped"
]
},
"status": "enabled"
}
},
"services": {
@ -48,10 +56,10 @@
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.2:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.6:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true
@ -61,18 +69,18 @@
"default/test.route-6b204d94623b3df4370c@kubernetescrd"
],
"serverStatus": {
"http://10.42.0.2:80": "UP",
"http://10.42.0.6:80": "UP"
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
},
"default/test2.route-23c7f4c450289ee29016@kubernetescrd": {
"loadBalancer": {
"servers": [
{
"url": "http://10.42.0.2:80"
"url": "http://10.42.0.3:80"
},
{
"url": "http://10.42.0.6:80"
"url": "http://10.42.0.5:80"
}
],
"passHostHeader": true
@ -82,8 +90,8 @@
"default/test2.route-23c7f4c450289ee29016@kubernetescrd"
],
"serverStatus": {
"http://10.42.0.2:80": "UP",
"http://10.42.0.6:80": "UP"
"http://10.42.0.3:80": "UP",
"http://10.42.0.5:80": "UP"
}
}
},
@ -109,10 +117,10 @@
"loadBalancer": {
"servers": [
{
"address": "10.42.0.4:8080"
"address": "10.42.0.6:8080"
},
{
"address": "10.42.0.5:8080"
"address": "10.42.0.7:8080"
}
]
},

View file

@ -15,6 +15,7 @@ import (
"github.com/containous/traefik/v2/pkg/config/dynamic"
"github.com/containous/traefik/v2/pkg/job"
"github.com/containous/traefik/v2/pkg/log"
"github.com/containous/traefik/v2/pkg/provider/kubernetes/crd/traefik/v1alpha1"
"github.com/containous/traefik/v2/pkg/safe"
"github.com/containous/traefik/v2/pkg/tls"
corev1 "k8s.io/api/core/v1"
@ -146,12 +147,62 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
}
for _, middleware := range client.GetMiddlewares() {
conf.HTTP.Middlewares[makeID(middleware.Namespace, middleware.Name)] = &middleware.Spec
id := makeID(middleware.Namespace, middleware.Name)
ctxMid := log.With(ctx, log.Str(log.MiddlewareName, id))
conf.HTTP.Middlewares[id] = &dynamic.Middleware{
AddPrefix: middleware.Spec.AddPrefix,
StripPrefix: middleware.Spec.StripPrefix,
StripPrefixRegex: middleware.Spec.StripPrefixRegex,
ReplacePath: middleware.Spec.ReplacePath,
ReplacePathRegex: middleware.Spec.ReplacePathRegex,
Chain: createChainMiddleware(ctxMid, middleware.Namespace, middleware.Spec.Chain),
IPWhiteList: middleware.Spec.IPWhiteList,
Headers: middleware.Spec.Headers,
Errors: middleware.Spec.Errors,
RateLimit: middleware.Spec.RateLimit,
RedirectRegex: middleware.Spec.RedirectRegex,
RedirectScheme: middleware.Spec.RedirectScheme,
BasicAuth: middleware.Spec.BasicAuth,
DigestAuth: middleware.Spec.DigestAuth,
ForwardAuth: middleware.Spec.ForwardAuth,
InFlightReq: middleware.Spec.InFlightReq,
Buffering: middleware.Spec.Buffering,
CircuitBreaker: middleware.Spec.CircuitBreaker,
Compress: middleware.Spec.Compress,
PassTLSClientCert: middleware.Spec.PassTLSClientCert,
Retry: middleware.Spec.Retry,
}
}
return conf
}
func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha1.Chain) *dynamic.Chain {
if chain == nil {
return nil
}
var mds []string
for _, mi := range chain.Middlewares {
if strings.Contains(mi.Name, "@") {
if len(mi.Namespace) > 0 {
log.FromContext(ctx).
Warnf("namespace %q is ignored in cross-provider context", mi.Namespace)
}
mds = append(mds, mi.Name)
continue
}
ns := mi.Namespace
if len(ns) == 0 {
ns = namespace
}
mds = append(mds, makeID(ns, mi.Name))
}
return &dynamic.Chain{Middlewares: mds}
}
func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options {
tlsOptionsCRD := client.GetTLSOptions()
var tlsOptions map[string]tls.Options

View file

@ -13,7 +13,41 @@ type Middleware struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec dynamic.Middleware `json:"spec"`
Spec MiddlewareSpec `json:"spec"`
}
// +k8s:deepcopy-gen=true
// Middleware holds the Middleware configuration.
type MiddlewareSpec struct {
AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty" toml:"addPrefix,omitempty" yaml:"addPrefix,omitempty"`
StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty" toml:"stripPrefix,omitempty" yaml:"stripPrefix,omitempty"`
StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty" toml:"stripPrefixRegex,omitempty" yaml:"stripPrefixRegex,omitempty"`
ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty" toml:"replacePath,omitempty" yaml:"replacePath,omitempty"`
ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty"`
Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty"`
IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty"`
Headers *dynamic.Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"`
Errors *dynamic.ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty"`
RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty"`
RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty" toml:"redirectRegex,omitempty" yaml:"redirectRegex,omitempty"`
RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty" toml:"redirectScheme,omitempty" yaml:"redirectScheme,omitempty"`
BasicAuth *dynamic.BasicAuth `json:"basicAuth,omitempty" toml:"basicAuth,omitempty" yaml:"basicAuth,omitempty"`
DigestAuth *dynamic.DigestAuth `json:"digestAuth,omitempty" toml:"digestAuth,omitempty" yaml:"digestAuth,omitempty"`
ForwardAuth *dynamic.ForwardAuth `json:"forwardAuth,omitempty" toml:"forwardAuth,omitempty" yaml:"forwardAuth,omitempty"`
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"`
Buffering *dynamic.Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"`
CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"`
Compress *dynamic.Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty"`
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"`
Retry *dynamic.Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"`
}
// +k8s:deepcopy-gen=true
// Chain holds a chain of middlewares
type Chain struct {
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View file

@ -29,9 +29,31 @@ THE SOFTWARE.
package v1alpha1
import (
dynamic "github.com/containous/traefik/v2/pkg/config/dynamic"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Chain) DeepCopyInto(out *Chain) {
*out = *in
if in.Middlewares != nil {
in, out := &in.Middlewares, &out.Middlewares
*out = make([]MiddlewareRef, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Chain.
func (in *Chain) DeepCopy() *Chain {
if in == nil {
return nil
}
out := new(Chain)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClientAuth) DeepCopyInto(out *ClientAuth) {
*out = *in
@ -338,6 +360,127 @@ func (in *MiddlewareRef) DeepCopy() *MiddlewareRef {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) {
*out = *in
if in.AddPrefix != nil {
in, out := &in.AddPrefix, &out.AddPrefix
*out = new(dynamic.AddPrefix)
**out = **in
}
if in.StripPrefix != nil {
in, out := &in.StripPrefix, &out.StripPrefix
*out = new(dynamic.StripPrefix)
(*in).DeepCopyInto(*out)
}
if in.StripPrefixRegex != nil {
in, out := &in.StripPrefixRegex, &out.StripPrefixRegex
*out = new(dynamic.StripPrefixRegex)
(*in).DeepCopyInto(*out)
}
if in.ReplacePath != nil {
in, out := &in.ReplacePath, &out.ReplacePath
*out = new(dynamic.ReplacePath)
**out = **in
}
if in.ReplacePathRegex != nil {
in, out := &in.ReplacePathRegex, &out.ReplacePathRegex
*out = new(dynamic.ReplacePathRegex)
**out = **in
}
if in.Chain != nil {
in, out := &in.Chain, &out.Chain
*out = new(Chain)
(*in).DeepCopyInto(*out)
}
if in.IPWhiteList != nil {
in, out := &in.IPWhiteList, &out.IPWhiteList
*out = new(dynamic.IPWhiteList)
(*in).DeepCopyInto(*out)
}
if in.Headers != nil {
in, out := &in.Headers, &out.Headers
*out = new(dynamic.Headers)
(*in).DeepCopyInto(*out)
}
if in.Errors != nil {
in, out := &in.Errors, &out.Errors
*out = new(dynamic.ErrorPage)
(*in).DeepCopyInto(*out)
}
if in.RateLimit != nil {
in, out := &in.RateLimit, &out.RateLimit
*out = new(dynamic.RateLimit)
(*in).DeepCopyInto(*out)
}
if in.RedirectRegex != nil {
in, out := &in.RedirectRegex, &out.RedirectRegex
*out = new(dynamic.RedirectRegex)
**out = **in
}
if in.RedirectScheme != nil {
in, out := &in.RedirectScheme, &out.RedirectScheme
*out = new(dynamic.RedirectScheme)
**out = **in
}
if in.BasicAuth != nil {
in, out := &in.BasicAuth, &out.BasicAuth
*out = new(dynamic.BasicAuth)
(*in).DeepCopyInto(*out)
}
if in.DigestAuth != nil {
in, out := &in.DigestAuth, &out.DigestAuth
*out = new(dynamic.DigestAuth)
(*in).DeepCopyInto(*out)
}
if in.ForwardAuth != nil {
in, out := &in.ForwardAuth, &out.ForwardAuth
*out = new(dynamic.ForwardAuth)
(*in).DeepCopyInto(*out)
}
if in.InFlightReq != nil {
in, out := &in.InFlightReq, &out.InFlightReq
*out = new(dynamic.InFlightReq)
(*in).DeepCopyInto(*out)
}
if in.Buffering != nil {
in, out := &in.Buffering, &out.Buffering
*out = new(dynamic.Buffering)
**out = **in
}
if in.CircuitBreaker != nil {
in, out := &in.CircuitBreaker, &out.CircuitBreaker
*out = new(dynamic.CircuitBreaker)
**out = **in
}
if in.Compress != nil {
in, out := &in.Compress, &out.Compress
*out = new(dynamic.Compress)
**out = **in
}
if in.PassTLSClientCert != nil {
in, out := &in.PassTLSClientCert, &out.PassTLSClientCert
*out = new(dynamic.PassTLSClientCert)
(*in).DeepCopyInto(*out)
}
if in.Retry != nil {
in, out := &in.Retry, &out.Retry
*out = new(dynamic.Retry)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MiddlewareSpec.
func (in *MiddlewareSpec) DeepCopy() *MiddlewareSpec {
if in == nil {
return nil
}
out := new(MiddlewareSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Route) DeepCopyInto(out *Route) {
*out = *in