The chain middleware in k8s use middlewareRef
This commit is contained in:
parent
261e7c1744
commit
770b3739e0
6 changed files with 269 additions and 21 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
38
integration/testdata/rawdata-crd.json
vendored
38
integration/testdata/rawdata-crd.json
vendored
|
@ -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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue