Allow config of additonal CircuitBreaker params
This commit is contained in:
parent
8c56d1a338
commit
71150bcaaf
15 changed files with 218 additions and 30 deletions
|
@ -171,15 +171,18 @@ This behavior cannot be configured.
|
||||||
|
|
||||||
### `CheckPeriod`
|
### `CheckPeriod`
|
||||||
|
|
||||||
The interval used to evaluate `expression` and decide if the state of the circuit breaker must change.
|
_Optional, Default="100ms"_
|
||||||
By default, `CheckPeriod` is 100ms. This value cannot be configured.
|
|
||||||
|
The interval between successive checks of the circuit breaker condition (when in standby state).
|
||||||
|
|
||||||
### `FallbackDuration`
|
### `FallbackDuration`
|
||||||
|
|
||||||
By default, `FallbackDuration` is 10 seconds. This value cannot be configured.
|
_Optional, Default="10s"_
|
||||||
|
|
||||||
### `RecoveringDuration`
|
The duration for which the circuit breaker will wait before trying to recover (from a tripped state).
|
||||||
|
|
||||||
The duration of the recovering mode (recovering state).
|
### `RecoveryDuration`
|
||||||
|
|
||||||
By default, `RecoveringDuration` is 10 seconds. This value cannot be configured.
|
_Optional, Default="10s"_
|
||||||
|
|
||||||
|
The duration for which the circuit breaker will try to recover (as soon as it is in recovering state).
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
- "traefik.http.middlewares.middleware02.buffering.retryexpression=foobar"
|
- "traefik.http.middlewares.middleware02.buffering.retryexpression=foobar"
|
||||||
- "traefik.http.middlewares.middleware03.chain.middlewares=foobar, foobar"
|
- "traefik.http.middlewares.middleware03.chain.middlewares=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware04.circuitbreaker.expression=foobar"
|
- "traefik.http.middlewares.middleware04.circuitbreaker.expression=foobar"
|
||||||
|
- "traefik.http.middlewares.middleware04.circuitbreaker.checkperiod=42s"
|
||||||
|
- "traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration=42s"
|
||||||
|
- "traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration=42s"
|
||||||
- "traefik.http.middlewares.middleware05.compress=true"
|
- "traefik.http.middlewares.middleware05.compress=true"
|
||||||
- "traefik.http.middlewares.middleware05.compress.excludedcontenttypes=foobar, foobar"
|
- "traefik.http.middlewares.middleware05.compress.excludedcontenttypes=foobar, foobar"
|
||||||
- "traefik.http.middlewares.middleware05.compress.minresponsebodybytes=42"
|
- "traefik.http.middlewares.middleware05.compress.minresponsebodybytes=42"
|
||||||
|
|
|
@ -125,6 +125,9 @@
|
||||||
[http.middlewares.Middleware04]
|
[http.middlewares.Middleware04]
|
||||||
[http.middlewares.Middleware04.circuitBreaker]
|
[http.middlewares.Middleware04.circuitBreaker]
|
||||||
expression = "foobar"
|
expression = "foobar"
|
||||||
|
checkPeriod = "42s"
|
||||||
|
fallbackDuration = "42s"
|
||||||
|
recoveryDuration = "42s"
|
||||||
[http.middlewares.Middleware05]
|
[http.middlewares.Middleware05]
|
||||||
[http.middlewares.Middleware05.compress]
|
[http.middlewares.Middleware05.compress]
|
||||||
excludedContentTypes = ["foobar", "foobar"]
|
excludedContentTypes = ["foobar", "foobar"]
|
||||||
|
|
|
@ -128,6 +128,9 @@ http:
|
||||||
Middleware04:
|
Middleware04:
|
||||||
circuitBreaker:
|
circuitBreaker:
|
||||||
expression: foobar
|
expression: foobar
|
||||||
|
checkPeriod: 42s
|
||||||
|
fallbackDuration: 42s
|
||||||
|
recoveryDuration: 42s
|
||||||
Middleware05:
|
Middleware05:
|
||||||
compress:
|
compress:
|
||||||
excludedContentTypes:
|
excludedContentTypes:
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
| `traefik/http/middlewares/Middleware02/buffering/retryExpression` | `foobar` |
|
| `traefik/http/middlewares/Middleware02/buffering/retryExpression` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware03/chain/middlewares/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware03/chain/middlewares/0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware03/chain/middlewares/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware03/chain/middlewares/1` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware04/circuitBreaker/checkPeriod` | `42s` |
|
||||||
| `traefik/http/middlewares/Middleware04/circuitBreaker/expression` | `foobar` |
|
| `traefik/http/middlewares/Middleware04/circuitBreaker/expression` | `foobar` |
|
||||||
|
| `traefik/http/middlewares/Middleware04/circuitBreaker/fallbackDuration` | `42s` |
|
||||||
|
| `traefik/http/middlewares/Middleware04/circuitBreaker/recoveryDuration` | `42s` |
|
||||||
| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/0` | `foobar` |
|
| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/0` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/1` | `foobar` |
|
| `traefik/http/middlewares/Middleware05/compress/excludedContentTypes/1` | `foobar` |
|
||||||
| `traefik/http/middlewares/Middleware05/compress/minResponseBodyBytes` | `42` |
|
| `traefik/http/middlewares/Middleware05/compress/minResponseBodyBytes` | `42` |
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
"traefik.http.middlewares.middleware02.buffering.retryexpression": "foobar",
|
"traefik.http.middlewares.middleware02.buffering.retryexpression": "foobar",
|
||||||
"traefik.http.middlewares.middleware03.chain.middlewares": "foobar, foobar",
|
"traefik.http.middlewares.middleware03.chain.middlewares": "foobar, foobar",
|
||||||
"traefik.http.middlewares.middleware04.circuitbreaker.expression": "foobar",
|
"traefik.http.middlewares.middleware04.circuitbreaker.expression": "foobar",
|
||||||
|
"traefik.http.middlewares.middleware04.circuitbreaker.checkperiod": "42s",
|
||||||
|
"traefik.http.middlewares.middleware04.circuitbreaker.fallbackduration": "42s",
|
||||||
|
"traefik.http.middlewares.middleware04.circuitbreaker.recoveryduration": "42s",
|
||||||
"traefik.http.middlewares.middleware05.compress": "true",
|
"traefik.http.middlewares.middleware05.compress": "true",
|
||||||
"traefik.http.middlewares.middleware05.compress.excludedcontenttypes": "foobar, foobar",
|
"traefik.http.middlewares.middleware05.compress.excludedcontenttypes": "foobar, foobar",
|
||||||
"traefik.http.middlewares.middleware05.compress.minresponsebodybytes": "42",
|
"traefik.http.middlewares.middleware05.compress.minresponsebodybytes": "42",
|
||||||
|
|
|
@ -91,8 +91,32 @@ spec:
|
||||||
circuitBreaker:
|
circuitBreaker:
|
||||||
description: CircuitBreaker holds the circuit breaker configuration.
|
description: CircuitBreaker holds the circuit breaker configuration.
|
||||||
properties:
|
properties:
|
||||||
|
checkPeriod:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: CheckPeriod is the interval between successive checks
|
||||||
|
of the circuit breaker condition (when in standby state).
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
expression:
|
expression:
|
||||||
|
description: Expression is the condition that triggers the tripped
|
||||||
|
state.
|
||||||
type: string
|
type: string
|
||||||
|
fallbackDuration:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: FallbackDuration is the duration for which the circuit
|
||||||
|
breaker will wait before trying to recover (from a tripped state).
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
recoveryDuration:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: RecoveryDuration is the duration for which the circuit
|
||||||
|
breaker will try to recover (as soon as it is in recovering
|
||||||
|
state).
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
type: object
|
type: object
|
||||||
compress:
|
compress:
|
||||||
description: Compress holds the compress configuration.
|
description: Compress holds the compress configuration.
|
||||||
|
|
|
@ -535,8 +535,32 @@ spec:
|
||||||
circuitBreaker:
|
circuitBreaker:
|
||||||
description: CircuitBreaker holds the circuit breaker configuration.
|
description: CircuitBreaker holds the circuit breaker configuration.
|
||||||
properties:
|
properties:
|
||||||
|
checkPeriod:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: CheckPeriod is the interval between successive checks
|
||||||
|
of the circuit breaker condition (when in standby state).
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
expression:
|
expression:
|
||||||
|
description: Expression is the condition that triggers the tripped
|
||||||
|
state.
|
||||||
type: string
|
type: string
|
||||||
|
fallbackDuration:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: FallbackDuration is the duration for which the circuit
|
||||||
|
breaker will wait before trying to recover (from a tripped state).
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
|
recoveryDuration:
|
||||||
|
anyOf:
|
||||||
|
- type: integer
|
||||||
|
- type: string
|
||||||
|
description: RecoveryDuration is the duration for which the circuit
|
||||||
|
breaker will try to recover (as soon as it is in recovering
|
||||||
|
state).
|
||||||
|
x-kubernetes-int-or-string: true
|
||||||
type: object
|
type: object
|
||||||
compress:
|
compress:
|
||||||
description: Compress holds the compress configuration.
|
description: Compress holds the compress configuration.
|
||||||
|
|
|
@ -93,7 +93,21 @@ type Chain struct {
|
||||||
|
|
||||||
// CircuitBreaker holds the circuit breaker configuration.
|
// CircuitBreaker holds the circuit breaker configuration.
|
||||||
type CircuitBreaker struct {
|
type CircuitBreaker struct {
|
||||||
|
// Expression is the condition that triggers the tripped state.
|
||||||
Expression string `json:"expression,omitempty" toml:"expression,omitempty" yaml:"expression,omitempty" export:"true"`
|
Expression string `json:"expression,omitempty" toml:"expression,omitempty" yaml:"expression,omitempty" export:"true"`
|
||||||
|
// CheckPeriod is the interval between successive checks of the circuit breaker condition (when in standby state).
|
||||||
|
CheckPeriod ptypes.Duration `json:"checkPeriod,omitempty" toml:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty" export:"true"`
|
||||||
|
// FallbackDuration is the duration for which the circuit breaker will wait before trying to recover (from a tripped state).
|
||||||
|
FallbackDuration ptypes.Duration `json:"fallbackDuration,omitempty" toml:"fallbackDuration,omitempty" yaml:"fallbackDuration,omitempty" export:"true"`
|
||||||
|
// RecoveryDuration is the duration for which the circuit breaker will try to recover (as soon as it is in recovering state).
|
||||||
|
RecoveryDuration ptypes.Duration `json:"recoveryDuration,omitempty" toml:"recoveryDuration,omitempty" yaml:"recoveryDuration,omitempty" export:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDefaults sets the default values on a RateLimit.
|
||||||
|
func (c *CircuitBreaker) SetDefaults() {
|
||||||
|
c.CheckPeriod = ptypes.Duration(100 * time.Millisecond)
|
||||||
|
c.FallbackDuration = ptypes.Duration(10 * time.Second)
|
||||||
|
c.RecoveryDuration = ptypes.Duration(10 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -27,6 +27,9 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
"traefik.http.middlewares.Middleware2.buffering.retryexpression": "foobar",
|
"traefik.http.middlewares.Middleware2.buffering.retryexpression": "foobar",
|
||||||
"traefik.http.middlewares.Middleware3.chain.middlewares": "foobar, fiibar",
|
"traefik.http.middlewares.Middleware3.chain.middlewares": "foobar, fiibar",
|
||||||
"traefik.http.middlewares.Middleware4.circuitbreaker.expression": "foobar",
|
"traefik.http.middlewares.Middleware4.circuitbreaker.expression": "foobar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware4.circuitbreaker.checkperiod": "1s",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware4.circuitbreaker.fallbackduration": "1s",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware4.circuitbreaker.recoveryduration": "1s",
|
||||||
"traefik.http.middlewares.Middleware5.digestauth.headerfield": "foobar",
|
"traefik.http.middlewares.Middleware5.digestauth.headerfield": "foobar",
|
||||||
"traefik.http.middlewares.Middleware5.digestauth.realm": "foobar",
|
"traefik.http.middlewares.Middleware5.digestauth.realm": "foobar",
|
||||||
"traefik.http.middlewares.Middleware5.digestauth.removeheader": "true",
|
"traefik.http.middlewares.Middleware5.digestauth.removeheader": "true",
|
||||||
|
@ -488,7 +491,10 @@ func TestDecodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
"Middleware4": {
|
"Middleware4": {
|
||||||
CircuitBreaker: &dynamic.CircuitBreaker{
|
CircuitBreaker: &dynamic.CircuitBreaker{
|
||||||
Expression: "foobar",
|
Expression: "foobar",
|
||||||
|
CheckPeriod: ptypes.Duration(time.Second),
|
||||||
|
FallbackDuration: ptypes.Duration(time.Second),
|
||||||
|
RecoveryDuration: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware5": {
|
"Middleware5": {
|
||||||
|
@ -983,7 +989,10 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
"Middleware4": {
|
"Middleware4": {
|
||||||
CircuitBreaker: &dynamic.CircuitBreaker{
|
CircuitBreaker: &dynamic.CircuitBreaker{
|
||||||
Expression: "foobar",
|
Expression: "foobar",
|
||||||
|
CheckPeriod: ptypes.Duration(time.Second),
|
||||||
|
FallbackDuration: ptypes.Duration(time.Second),
|
||||||
|
RecoveryDuration: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware5": {
|
"Middleware5": {
|
||||||
|
@ -1191,6 +1200,9 @@ func TestEncodeConfiguration(t *testing.T) {
|
||||||
"traefik.HTTP.Middlewares.Middleware2.Buffering.RetryExpression": "foobar",
|
"traefik.HTTP.Middlewares.Middleware2.Buffering.RetryExpression": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware3.Chain.Middlewares": "foobar, fiibar",
|
"traefik.HTTP.Middlewares.Middleware3.Chain.Middlewares": "foobar, fiibar",
|
||||||
"traefik.HTTP.Middlewares.Middleware4.CircuitBreaker.Expression": "foobar",
|
"traefik.HTTP.Middlewares.Middleware4.CircuitBreaker.Expression": "foobar",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware4.CircuitBreaker.CheckPeriod": "1000000000",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware4.CircuitBreaker.FallbackDuration": "1000000000",
|
||||||
|
"traefik.HTTP.Middlewares.Middleware4.CircuitBreaker.RecoveryDuration": "1000000000",
|
||||||
"traefik.HTTP.Middlewares.Middleware5.DigestAuth.HeaderField": "foobar",
|
"traefik.HTTP.Middlewares.Middleware5.DigestAuth.HeaderField": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware5.DigestAuth.Realm": "foobar",
|
"traefik.HTTP.Middlewares.Middleware5.DigestAuth.Realm": "foobar",
|
||||||
"traefik.HTTP.Middlewares.Middleware5.DigestAuth.RemoveHeader": "true",
|
"traefik.HTTP.Middlewares.Middleware5.DigestAuth.RemoveHeader": "true",
|
||||||
|
|
|
@ -3,6 +3,7 @@ package circuitbreaker
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/opentracing/opentracing-go/ext"
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||||
|
@ -12,9 +13,7 @@ import (
|
||||||
"github.com/vulcand/oxy/cbreaker"
|
"github.com/vulcand/oxy/cbreaker"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const typeName = "CircuitBreaker"
|
||||||
typeName = "CircuitBreaker"
|
|
||||||
)
|
|
||||||
|
|
||||||
type circuitBreaker struct {
|
type circuitBreaker struct {
|
||||||
circuitBreaker *cbreaker.CircuitBreaker
|
circuitBreaker *cbreaker.CircuitBreaker
|
||||||
|
@ -27,9 +26,32 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ
|
||||||
|
|
||||||
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName))
|
||||||
logger.Debug("Creating middleware")
|
logger.Debug("Creating middleware")
|
||||||
logger.Debug("Setting up with expression: %s", expression)
|
logger.Debugf("Setting up with expression: %s", expression)
|
||||||
|
|
||||||
oxyCircuitBreaker, err := cbreaker.New(next, expression, createCircuitBreakerOptions(expression))
|
cbOpts := []cbreaker.CircuitBreakerOption{
|
||||||
|
cbreaker.Fallback(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
tracing.SetErrorWithEvent(req, "blocked by circuit-breaker (%q)", expression)
|
||||||
|
rw.WriteHeader(http.StatusServiceUnavailable)
|
||||||
|
|
||||||
|
if _, err := rw.Write([]byte(http.StatusText(http.StatusServiceUnavailable))); err != nil {
|
||||||
|
log.FromContext(req.Context()).Error(err)
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
|
||||||
|
if confCircuitBreaker.CheckPeriod > 0 {
|
||||||
|
cbOpts = append(cbOpts, cbreaker.CheckPeriod(time.Duration(confCircuitBreaker.CheckPeriod)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if confCircuitBreaker.FallbackDuration > 0 {
|
||||||
|
cbOpts = append(cbOpts, cbreaker.FallbackDuration(time.Duration(confCircuitBreaker.FallbackDuration)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if confCircuitBreaker.RecoveryDuration > 0 {
|
||||||
|
cbOpts = append(cbOpts, cbreaker.RecoveryDuration(time.Duration(confCircuitBreaker.RecoveryDuration)))
|
||||||
|
}
|
||||||
|
|
||||||
|
oxyCircuitBreaker, err := cbreaker.New(next, expression, cbOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -39,18 +61,6 @@ func New(ctx context.Context, next http.Handler, confCircuitBreaker dynamic.Circ
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCircuitBreakerOptions returns a new CircuitBreakerOption.
|
|
||||||
func createCircuitBreakerOptions(expression string) cbreaker.CircuitBreakerOption {
|
|
||||||
return cbreaker.Fallback(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
tracing.SetErrorWithEvent(req, "blocked by circuit-breaker (%q)", expression)
|
|
||||||
rw.WriteHeader(http.StatusServiceUnavailable)
|
|
||||||
|
|
||||||
if _, err := rw.Write([]byte(http.StatusText(http.StatusServiceUnavailable))); err != nil {
|
|
||||||
log.FromContext(req.Context()).Error(err)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *circuitBreaker) GetTracingInformation() (string, ext.SpanKindEnum) {
|
func (c *circuitBreaker) GetTracingInformation() (string, ext.SpanKindEnum) {
|
||||||
return c.name, tracing.SpanKindNoneEnum
|
return c.name, tracing.SpanKindNoneEnum
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,12 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
circuitBreaker, err := createCircuitBreakerMiddleware(middleware.Spec.CircuitBreaker)
|
||||||
|
if err != nil {
|
||||||
|
log.FromContext(ctxMid).Errorf("Error while reading circuit breaker middleware: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
conf.HTTP.Middlewares[id] = &dynamic.Middleware{
|
conf.HTTP.Middlewares[id] = &dynamic.Middleware{
|
||||||
AddPrefix: middleware.Spec.AddPrefix,
|
AddPrefix: middleware.Spec.AddPrefix,
|
||||||
StripPrefix: middleware.Spec.StripPrefix,
|
StripPrefix: middleware.Spec.StripPrefix,
|
||||||
|
@ -261,7 +267,7 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
||||||
ForwardAuth: forwardAuth,
|
ForwardAuth: forwardAuth,
|
||||||
InFlightReq: middleware.Spec.InFlightReq,
|
InFlightReq: middleware.Spec.InFlightReq,
|
||||||
Buffering: middleware.Spec.Buffering,
|
Buffering: middleware.Spec.Buffering,
|
||||||
CircuitBreaker: middleware.Spec.CircuitBreaker,
|
CircuitBreaker: circuitBreaker,
|
||||||
Compress: middleware.Spec.Compress,
|
Compress: middleware.Spec.Compress,
|
||||||
PassTLSClientCert: middleware.Spec.PassTLSClientCert,
|
PassTLSClientCert: middleware.Spec.PassTLSClientCert,
|
||||||
Retry: retry,
|
Retry: retry,
|
||||||
|
@ -425,6 +431,35 @@ func createPluginMiddleware(plugins map[string]apiextensionv1.JSON) (map[string]
|
||||||
return pc, nil
|
return pc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createCircuitBreakerMiddleware(circuitBreaker *v1alpha1.CircuitBreaker) (*dynamic.CircuitBreaker, error) {
|
||||||
|
if circuitBreaker == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cb := &dynamic.CircuitBreaker{Expression: circuitBreaker.Expression}
|
||||||
|
cb.SetDefaults()
|
||||||
|
|
||||||
|
if circuitBreaker.CheckPeriod != nil {
|
||||||
|
if err := cb.CheckPeriod.Set(circuitBreaker.CheckPeriod.String()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if circuitBreaker.FallbackDuration != nil {
|
||||||
|
if err := cb.FallbackDuration.Set(circuitBreaker.FallbackDuration.String()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if circuitBreaker.RecoveryDuration != nil {
|
||||||
|
if err := cb.RecoveryDuration.Set(circuitBreaker.RecoveryDuration.String()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb, nil
|
||||||
|
}
|
||||||
|
|
||||||
func createRateLimitMiddleware(rateLimit *v1alpha1.RateLimit) (*dynamic.RateLimit, error) {
|
func createRateLimitMiddleware(rateLimit *v1alpha1.RateLimit) (*dynamic.RateLimit, error) {
|
||||||
if rateLimit == nil {
|
if rateLimit == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
@ -40,7 +40,7 @@ type MiddlewareSpec struct {
|
||||||
ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"`
|
ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"`
|
||||||
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"`
|
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"`
|
||||||
Buffering *dynamic.Buffering `json:"buffering,omitempty"`
|
Buffering *dynamic.Buffering `json:"buffering,omitempty"`
|
||||||
CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty"`
|
CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty"`
|
||||||
Compress *dynamic.Compress `json:"compress,omitempty"`
|
Compress *dynamic.Compress `json:"compress,omitempty"`
|
||||||
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"`
|
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"`
|
||||||
Retry *Retry `json:"retry,omitempty"`
|
Retry *Retry `json:"retry,omitempty"`
|
||||||
|
@ -59,6 +59,20 @@ type ErrorPage struct {
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
|
// CircuitBreaker holds the circuit breaker configuration.
|
||||||
|
type CircuitBreaker struct {
|
||||||
|
// Expression is the condition that triggers the tripped state.
|
||||||
|
Expression string `json:"expression,omitempty" toml:"expression,omitempty" yaml:"expression,omitempty" export:"true"`
|
||||||
|
// CheckPeriod is the interval between successive checks of the circuit breaker condition (when in standby state).
|
||||||
|
CheckPeriod *intstr.IntOrString `json:"checkPeriod,omitempty" toml:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty" export:"true"`
|
||||||
|
// FallbackDuration is the duration for which the circuit breaker will wait before trying to recover (from a tripped state).
|
||||||
|
FallbackDuration *intstr.IntOrString `json:"fallbackDuration,omitempty" toml:"fallbackDuration,omitempty" yaml:"fallbackDuration,omitempty" export:"true"`
|
||||||
|
// RecoveryDuration is the duration for which the circuit breaker will try to recover (as soon as it is in recovering state).
|
||||||
|
RecoveryDuration *intstr.IntOrString `json:"recoveryDuration,omitempty" toml:"recoveryDuration,omitempty" yaml:"recoveryDuration,omitempty" export:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
||||||
// Chain holds a chain of middlewares.
|
// Chain holds a chain of middlewares.
|
||||||
type Chain struct {
|
type Chain struct {
|
||||||
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
|
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
|
||||||
|
|
|
@ -74,6 +74,37 @@ func (in *Chain) DeepCopy() *Chain {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *CircuitBreaker) DeepCopyInto(out *CircuitBreaker) {
|
||||||
|
*out = *in
|
||||||
|
if in.CheckPeriod != nil {
|
||||||
|
in, out := &in.CheckPeriod, &out.CheckPeriod
|
||||||
|
*out = new(intstr.IntOrString)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.FallbackDuration != nil {
|
||||||
|
in, out := &in.FallbackDuration, &out.FallbackDuration
|
||||||
|
*out = new(intstr.IntOrString)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.RecoveryDuration != nil {
|
||||||
|
in, out := &in.RecoveryDuration, &out.RecoveryDuration
|
||||||
|
*out = new(intstr.IntOrString)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CircuitBreaker.
|
||||||
|
func (in *CircuitBreaker) DeepCopy() *CircuitBreaker {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(CircuitBreaker)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ClientAuth) DeepCopyInto(out *ClientAuth) {
|
func (in *ClientAuth) DeepCopyInto(out *ClientAuth) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
@ -714,8 +745,8 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) {
|
||||||
}
|
}
|
||||||
if in.CircuitBreaker != nil {
|
if in.CircuitBreaker != nil {
|
||||||
in, out := &in.CircuitBreaker, &out.CircuitBreaker
|
in, out := &in.CircuitBreaker, &out.CircuitBreaker
|
||||||
*out = new(dynamic.CircuitBreaker)
|
*out = new(CircuitBreaker)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.Compress != nil {
|
if in.Compress != nil {
|
||||||
in, out := &in.Compress, &out.Compress
|
in, out := &in.Compress, &out.Compress
|
||||||
|
|
|
@ -173,6 +173,9 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
"traefik/http/middlewares/Middleware03/chain/middlewares/0": "foobar",
|
"traefik/http/middlewares/Middleware03/chain/middlewares/0": "foobar",
|
||||||
"traefik/http/middlewares/Middleware03/chain/middlewares/1": "foobar",
|
"traefik/http/middlewares/Middleware03/chain/middlewares/1": "foobar",
|
||||||
"traefik/http/middlewares/Middleware04/circuitBreaker/expression": "foobar",
|
"traefik/http/middlewares/Middleware04/circuitBreaker/expression": "foobar",
|
||||||
|
"traefik/http/middlewares/Middleware04/circuitBreaker/checkPeriod": "1s",
|
||||||
|
"traefik/http/middlewares/Middleware04/circuitBreaker/fallbackDuration": "1s",
|
||||||
|
"traefik/http/middlewares/Middleware04/circuitBreaker/recoveryDuration": "1s",
|
||||||
"traefik/http/middlewares/Middleware07/errors/status/0": "foobar",
|
"traefik/http/middlewares/Middleware07/errors/status/0": "foobar",
|
||||||
"traefik/http/middlewares/Middleware07/errors/status/1": "foobar",
|
"traefik/http/middlewares/Middleware07/errors/status/1": "foobar",
|
||||||
"traefik/http/middlewares/Middleware07/errors/service": "foobar",
|
"traefik/http/middlewares/Middleware07/errors/service": "foobar",
|
||||||
|
@ -393,7 +396,10 @@ func Test_buildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
"Middleware04": {
|
"Middleware04": {
|
||||||
CircuitBreaker: &dynamic.CircuitBreaker{
|
CircuitBreaker: &dynamic.CircuitBreaker{
|
||||||
Expression: "foobar",
|
Expression: "foobar",
|
||||||
|
CheckPeriod: ptypes.Duration(time.Second),
|
||||||
|
FallbackDuration: ptypes.Duration(time.Second),
|
||||||
|
RecoveryDuration: ptypes.Duration(time.Second),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Middleware05": {
|
"Middleware05": {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue