Move dynamic config into a dedicated package.
This commit is contained in:
parent
09cc1161c9
commit
c8bf8e896a
102 changed files with 3170 additions and 3166 deletions
36
pkg/config/dynamic/config.go
Normal file
36
pkg/config/dynamic/config.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package dynamic
|
||||
|
||||
import (
|
||||
"github.com/containous/traefik/pkg/tls"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Message holds configuration information exchanged between parts of traefik.
|
||||
type Message struct {
|
||||
ProviderName string
|
||||
Configuration *Configuration
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Configurations is for currentConfigurations Map.
|
||||
type Configurations map[string]*Configuration
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Configuration is the root of the dynamic configuration
|
||||
type Configuration struct {
|
||||
HTTP *HTTPConfiguration `json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty"`
|
||||
TCP *TCPConfiguration `json:"tcp,omitempty" toml:"tcp,omitempty" yaml:"tcp,omitempty"`
|
||||
TLS *TLSConfiguration `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TLSConfiguration contains all the configuration parameters of a TLS connection.
|
||||
type TLSConfiguration struct {
|
||||
Certificates []*tls.CertAndStores `json:"-" toml:"certificates,omitempty" yaml:"certificates,omitempty" label:"-"`
|
||||
Options map[string]tls.Options `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
||||
Stores map[string]tls.Store `json:"stores,omitempty" toml:"stores,omitempty" yaml:"stores,omitempty"`
|
||||
}
|
37
pkg/config/dynamic/config_test.go
Normal file
37
pkg/config/dynamic/config_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package dynamic
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDeepCopy(t *testing.T) {
|
||||
cfg := &Configuration{}
|
||||
_, err := toml.DecodeFile("./fixtures/sample.toml", &cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfgCopy := cfg
|
||||
assert.Equal(t, reflect.ValueOf(cfgCopy), reflect.ValueOf(cfg))
|
||||
assert.Equal(t, reflect.ValueOf(cfgCopy), reflect.ValueOf(cfg))
|
||||
assert.Equal(t, cfgCopy, cfg)
|
||||
|
||||
cfgDeepCopy := cfg.DeepCopy()
|
||||
assert.NotEqual(t, reflect.ValueOf(cfgDeepCopy), reflect.ValueOf(cfg))
|
||||
assert.Equal(t, reflect.TypeOf(cfgDeepCopy), reflect.TypeOf(cfg))
|
||||
assert.Equal(t, cfgDeepCopy, cfg)
|
||||
|
||||
// Update cfg
|
||||
cfg.HTTP.Routers["powpow"] = &Router{}
|
||||
|
||||
assert.Equal(t, reflect.ValueOf(cfgCopy), reflect.ValueOf(cfg))
|
||||
assert.Equal(t, reflect.ValueOf(cfgCopy), reflect.ValueOf(cfg))
|
||||
assert.Equal(t, cfgCopy, cfg)
|
||||
|
||||
assert.NotEqual(t, reflect.ValueOf(cfgDeepCopy), reflect.ValueOf(cfg))
|
||||
assert.Equal(t, reflect.TypeOf(cfgDeepCopy), reflect.TypeOf(cfg))
|
||||
assert.NotEqual(t, cfgDeepCopy, cfg)
|
||||
}
|
481
pkg/config/dynamic/fixtures/sample.toml
Normal file
481
pkg/config/dynamic/fixtures/sample.toml
Normal file
|
@ -0,0 +1,481 @@
|
|||
[global]
|
||||
checkNewVersion = true
|
||||
sendAnonymousUsage = true
|
||||
|
||||
[serversTransport]
|
||||
insecureSkipVerify = true
|
||||
rootCAs = ["foobar", "foobar"]
|
||||
maxIdleConnsPerHost = 42
|
||||
[serversTransport.forwardingTimeouts]
|
||||
dialTimeout = 42
|
||||
responseHeaderTimeout = 42
|
||||
idleConnTimeout = 42
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.EntryPoint0]
|
||||
address = "foobar"
|
||||
[entryPoints.EntryPoint0.transport]
|
||||
[entryPoints.EntryPoint0.transport.lifeCycle]
|
||||
requestAcceptGraceTimeout = 42
|
||||
graceTimeOut = 42
|
||||
[entryPoints.EntryPoint0.transport.respondingTimeouts]
|
||||
readTimeout = 42
|
||||
writeTimeout = 42
|
||||
idleTimeout = 42
|
||||
[entryPoints.EntryPoint0.proxyProtocol]
|
||||
insecure = true
|
||||
trustedIPs = ["foobar", "foobar"]
|
||||
[entryPoints.EntryPoint0.forwardedHeaders]
|
||||
insecure = true
|
||||
trustedIPs = ["foobar", "foobar"]
|
||||
|
||||
[providers]
|
||||
providersThrottleDuration = 42
|
||||
[providers.docker]
|
||||
constraints = "foobar"
|
||||
watch = true
|
||||
endpoint = "foobar"
|
||||
defaultRule = "foobar"
|
||||
exposedByDefault = true
|
||||
useBindPortIP = true
|
||||
swarmMode = true
|
||||
network = "foobar"
|
||||
swarmModeRefreshSeconds = 42
|
||||
[providers.docker.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
cert = "foobar"
|
||||
key = "foobar"
|
||||
insecureSkipVerify = true
|
||||
[providers.file]
|
||||
directory = "foobar"
|
||||
watch = true
|
||||
filename = "foobar"
|
||||
debugLogGeneratedTemplate = true
|
||||
traefikFile = "foobar"
|
||||
[providers.marathon]
|
||||
constraints = "foobar"
|
||||
trace = true
|
||||
watch = true
|
||||
endpoint = "foobar"
|
||||
defaultRule = "foobar"
|
||||
exposedByDefault = true
|
||||
dcosToken = "foobar"
|
||||
dialerTimeout = 42
|
||||
responseHeaderTimeout = 42
|
||||
tlsHandshakeTimeout = 42
|
||||
keepAlive = 42
|
||||
forceTaskHostname = true
|
||||
respectReadinessChecks = true
|
||||
[providers.marathon.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
cert = "foobar"
|
||||
key = "foobar"
|
||||
insecureSkipVerify = true
|
||||
[providers.marathon.basic]
|
||||
httpBasicAuthUser = "foobar"
|
||||
httpBasicPassword = "foobar"
|
||||
[providers.kubernetesIngress]
|
||||
endpoint = "foobar"
|
||||
token = "foobar"
|
||||
certAuthFilePath = "foobar"
|
||||
disablePassHostHeaders = true
|
||||
namespaces = ["foobar", "foobar"]
|
||||
labelSelector = "foobar"
|
||||
ingressClass = "foobar"
|
||||
[providers.kubernetesIngress.ingressEndpoint]
|
||||
ip = "foobar"
|
||||
hostname = "foobar"
|
||||
publishedService = "foobar"
|
||||
[providers.kubernetesCRD]
|
||||
endpoint = "foobar"
|
||||
token = "foobar"
|
||||
certAuthFilePath = "foobar"
|
||||
disablePassHostHeaders = true
|
||||
namespaces = ["foobar", "foobar"]
|
||||
labelSelector = "foobar"
|
||||
ingressClass = "foobar"
|
||||
[providers.rest]
|
||||
entryPoint = "foobar"
|
||||
[providers.rancher]
|
||||
constraints = "foobar"
|
||||
watch = true
|
||||
defaultRule = "foobar"
|
||||
exposedByDefault = true
|
||||
enableServiceHealthFilter = true
|
||||
refreshSeconds = 42
|
||||
intervalPoll = true
|
||||
prefix = "foobar"
|
||||
|
||||
[api]
|
||||
entryPoint = "foobar"
|
||||
dashboard = true
|
||||
middlewares = ["foobar", "foobar"]
|
||||
[api.statistics]
|
||||
recentErrors = 42
|
||||
|
||||
[metrics]
|
||||
[metrics.prometheus]
|
||||
buckets = [42.0, 42.0]
|
||||
entryPoint = "foobar"
|
||||
middlewares = ["foobar", "foobar"]
|
||||
[metrics.dataDog]
|
||||
address = "foobar"
|
||||
pushInterval = "10s"
|
||||
[metrics.statsD]
|
||||
address = "foobar"
|
||||
pushInterval = "10s"
|
||||
[metrics.influxDB]
|
||||
address = "foobar"
|
||||
protocol = "foobar"
|
||||
pushInterval = "10s"
|
||||
database = "foobar"
|
||||
retentionPolicy = "foobar"
|
||||
username = "foobar"
|
||||
password = "foobar"
|
||||
|
||||
[ping]
|
||||
entryPoint = "foobar"
|
||||
middlewares = ["foobar", "foobar"]
|
||||
|
||||
[log]
|
||||
level = "foobar"
|
||||
filePath = "foobar"
|
||||
format = "foobar"
|
||||
|
||||
[accessLog]
|
||||
filePath = "foobar"
|
||||
format = "foobar"
|
||||
bufferingSize = 42
|
||||
[accessLog.filters]
|
||||
statusCodes = ["foobar", "foobar"]
|
||||
retryAttempts = true
|
||||
minDuration = 42
|
||||
[accessLog.fields]
|
||||
defaultMode = "foobar"
|
||||
[accessLog.fields.names]
|
||||
name0 = "foobar"
|
||||
name1 = "foobar"
|
||||
[accessLog.fields.headers]
|
||||
defaultMode = "foobar"
|
||||
[accessLog.fields.headers.names]
|
||||
name0 = "foobar"
|
||||
name1 = "foobar"
|
||||
|
||||
[tracing]
|
||||
serviceName = "foobar"
|
||||
spanNameLimit = 42
|
||||
[tracing.jaeger]
|
||||
samplingServerURL = "foobar"
|
||||
samplingType = "foobar"
|
||||
samplingParam = 42.0
|
||||
localAgentHostPort = "foobar"
|
||||
gen128Bit = true
|
||||
propagation = "foobar"
|
||||
traceContextHeaderName = "foobar"
|
||||
[tracing.zipkin]
|
||||
httpEndpoint = "foobar"
|
||||
sameSpan = true
|
||||
id128Bit = true
|
||||
debug = true
|
||||
sampleRate = 42.0
|
||||
[tracing.dataDog]
|
||||
localAgentHostPort = "foobar"
|
||||
globalTag = "foobar"
|
||||
debug = true
|
||||
prioritySampling = true
|
||||
traceIDHeaderName = "foobar"
|
||||
parentIDHeaderName = "foobar"
|
||||
samplingPriorityHeaderName = "foobar"
|
||||
bagagePrefixHeaderName = "foobar"
|
||||
[tracing.instana]
|
||||
localAgentHost = "foobar"
|
||||
localAgentPort = 42
|
||||
logLevel = "foobar"
|
||||
[tracing.haystack]
|
||||
localAgentHost = "foobar"
|
||||
localAgentPort = 42
|
||||
globalTag = "foobar"
|
||||
traceIDHeaderName = "foobar"
|
||||
parentIDHeaderName = "foobar"
|
||||
spanIDHeaderName = "foobar"
|
||||
|
||||
[hostResolver]
|
||||
cnameFlattening = true
|
||||
resolvConfig = "foobar"
|
||||
resolvDepth = 42
|
||||
|
||||
[acme]
|
||||
email = "foobar"
|
||||
acmeLogging = true
|
||||
caServer = "foobar"
|
||||
storage = "foobar"
|
||||
entryPoint = "foobar"
|
||||
keyType = "foobar"
|
||||
onHostRule = true
|
||||
[acme.dnsChallenge]
|
||||
provider = "foobar"
|
||||
delayBeforeCheck = 42
|
||||
resolvers = ["foobar", "foobar"]
|
||||
disablePropagationCheck = true
|
||||
[acme.httpChallenge]
|
||||
entryPoint = "foobar"
|
||||
[acme.tlsChallenge]
|
||||
|
||||
[[acme.domains]]
|
||||
main = "foobar"
|
||||
sans = ["foobar", "foobar"]
|
||||
|
||||
[[acme.domains]]
|
||||
main = "foobar"
|
||||
sans = ["foobar", "foobar"]
|
||||
|
||||
## Dynamic configuration
|
||||
|
||||
[http]
|
||||
[http.routers]
|
||||
[http.routers.Router0]
|
||||
entryPoints = ["foobar", "foobar"]
|
||||
middlewares = ["foobar", "foobar"]
|
||||
service = "foobar"
|
||||
rule = "foobar"
|
||||
priority = 42
|
||||
[http.routers.Router0.tls]
|
||||
[http.middlewares]
|
||||
[http.middlewares.Middleware0]
|
||||
[http.middlewares.Middleware0.addPrefix]
|
||||
prefix = "foobar"
|
||||
[http.middlewares.Middleware1]
|
||||
[http.middlewares.Middleware1.stripPrefix]
|
||||
prefixes = ["foobar", "foobar"]
|
||||
[http.middlewares.Middleware10]
|
||||
[http.middlewares.Middleware10.rateLimit]
|
||||
extractorFunc = "foobar"
|
||||
[http.middlewares.Middleware10.rateLimit.rateSet]
|
||||
[http.middlewares.Middleware10.rateLimit.rateSet.Rate0]
|
||||
period = 42000000000
|
||||
average = 42
|
||||
burst = 42
|
||||
[http.middlewares.Middleware10.rateLimit.rateSet.Rate1]
|
||||
period = 42000000000
|
||||
average = 42
|
||||
burst = 42
|
||||
[http.middlewares.Middleware11]
|
||||
[http.middlewares.Middleware11.redirectRegex]
|
||||
regex = "foobar"
|
||||
replacement = "foobar"
|
||||
permanent = true
|
||||
[http.middlewares.Middleware12]
|
||||
[http.middlewares.Middleware12.redirectScheme]
|
||||
scheme = "foobar"
|
||||
port = "foobar"
|
||||
permanent = true
|
||||
[http.middlewares.Middleware13]
|
||||
[http.middlewares.Middleware13.basicAuth]
|
||||
users = ["foobar", "foobar"]
|
||||
usersFile = "foobar"
|
||||
realm = "foobar"
|
||||
removeHeader = true
|
||||
headerField = "foobar"
|
||||
[http.middlewares.Middleware14]
|
||||
[http.middlewares.Middleware14.digestAuth]
|
||||
users = ["foobar", "foobar"]
|
||||
usersFile = "foobar"
|
||||
removeHeader = true
|
||||
realm = "foobar"
|
||||
headerField = "foobar"
|
||||
[http.middlewares.Middleware15]
|
||||
[http.middlewares.Middleware15.forwardAuth]
|
||||
address = "foobar"
|
||||
trustForwardHeader = true
|
||||
authResponseHeaders = ["foobar", "foobar"]
|
||||
[http.middlewares.Middleware15.forwardAuth.tls]
|
||||
ca = "foobar"
|
||||
caOptional = true
|
||||
cert = "foobar"
|
||||
key = "foobar"
|
||||
insecureSkipVerify = true
|
||||
[http.middlewares.Middleware16]
|
||||
[http.middlewares.Middleware16.maxConn]
|
||||
amount = 42
|
||||
extractorFunc = "foobar"
|
||||
[http.middlewares.Middleware17]
|
||||
[http.middlewares.Middleware17.buffering]
|
||||
maxRequestBodyBytes = 42
|
||||
memRequestBodyBytes = 42
|
||||
maxResponseBodyBytes = 42
|
||||
memResponseBodyBytes = 42
|
||||
retryExpression = "foobar"
|
||||
[http.middlewares.Middleware18]
|
||||
[http.middlewares.Middleware18.circuitBreaker]
|
||||
expression = "foobar"
|
||||
[http.middlewares.Middleware19]
|
||||
[http.middlewares.Middleware19.compress]
|
||||
[http.middlewares.Middleware2]
|
||||
[http.middlewares.Middleware2.stripPrefixRegex]
|
||||
regex = ["foobar", "foobar"]
|
||||
[http.middlewares.Middleware20]
|
||||
[http.middlewares.Middleware20.passTLSClientCert]
|
||||
pem = true
|
||||
[http.middlewares.Middleware20.passTLSClientCert.info]
|
||||
notAfter = true
|
||||
notBefore = true
|
||||
sans = true
|
||||
[http.middlewares.Middleware20.passTLSClientCert.info.subject]
|
||||
country = true
|
||||
province = true
|
||||
locality = true
|
||||
organization = true
|
||||
commonName = true
|
||||
serialNumber = true
|
||||
domainComponent = true
|
||||
[http.middlewares.Middleware20.passTLSClientCert.info.issuer]
|
||||
country = true
|
||||
province = true
|
||||
locality = true
|
||||
organization = true
|
||||
commonName = true
|
||||
serialNumber = true
|
||||
domainComponent = true
|
||||
[http.middlewares.Middleware21]
|
||||
[http.middlewares.Middleware21.retry]
|
||||
regex = 0
|
||||
[http.middlewares.Middleware3]
|
||||
[http.middlewares.Middleware3.replacePath]
|
||||
path = "foobar"
|
||||
[http.middlewares.Middleware4]
|
||||
[http.middlewares.Middleware4.replacePathRegex]
|
||||
regex = "foobar"
|
||||
replacement = "foobar"
|
||||
[http.middlewares.Middleware5]
|
||||
[http.middlewares.Middleware5.chain]
|
||||
middlewares = ["foobar", "foobar"]
|
||||
[http.middlewares.Middleware6]
|
||||
[http.middlewares.Middleware6.ipWhiteList]
|
||||
sourceRange = ["foobar", "foobar"]
|
||||
[http.middlewares.Middleware7]
|
||||
[http.middlewares.Middleware7.ipWhiteList]
|
||||
[http.middlewares.Middleware7.ipWhiteList.ipStrategy]
|
||||
depth = 42
|
||||
excludedIPs = ["foobar", "foobar"]
|
||||
[http.middlewares.Middleware8]
|
||||
[http.middlewares.Middleware8.headers]
|
||||
accessControlAllowCredentials = true
|
||||
accessControlAllowHeaders = ["foobar", "foobar"]
|
||||
accessControlAllowMethods = ["foobar", "foobar"]
|
||||
accessControlAllowOrigin = "foobar"
|
||||
accessControlExposeHeaders = ["foobar", "foobar"]
|
||||
accessControlMaxAge = 42
|
||||
addVaryHeader = true
|
||||
allowedHosts = ["foobar", "foobar"]
|
||||
hostsProxyHeaders = ["foobar", "foobar"]
|
||||
sslRedirect = true
|
||||
sslTemporaryRedirect = true
|
||||
sslHost = "foobar"
|
||||
sslForceHost = true
|
||||
stsSeconds = 42
|
||||
stsIncludeSubdomains = true
|
||||
stsPreload = true
|
||||
forceSTSHeader = true
|
||||
frameDeny = true
|
||||
customFrameOptionsValue = "foobar"
|
||||
contentTypeNosniff = true
|
||||
browserXssFilter = true
|
||||
customBrowserXSSValue = "foobar"
|
||||
contentSecurityPolicy = "foobar"
|
||||
publicKey = "foobar"
|
||||
referrerPolicy = "foobar"
|
||||
isDevelopment = true
|
||||
[http.middlewares.Middleware8.headers.customRequestHeaders]
|
||||
name0 = "foobar"
|
||||
name1 = "foobar"
|
||||
[http.middlewares.Middleware8.headers.customResponseHeaders]
|
||||
name0 = "foobar"
|
||||
name1 = "foobar"
|
||||
[http.middlewares.Middleware8.headers.sslProxyHeaders]
|
||||
name0 = "foobar"
|
||||
name1 = "foobar"
|
||||
[http.middlewares.Middleware9]
|
||||
[http.middlewares.Middleware9.errors]
|
||||
status = ["foobar", "foobar"]
|
||||
service = "foobar"
|
||||
query = "foobar"
|
||||
[http.services]
|
||||
[http.services.Service0]
|
||||
[http.services.Service0.loadBalancer]
|
||||
passHostHeader = true
|
||||
[http.services.Service0.loadBalancer.stickiness]
|
||||
cookieName = "foobar"
|
||||
|
||||
[[http.services.Service0.loadBalancer.servers]]
|
||||
url = "foobar"
|
||||
|
||||
[[http.services.Service0.loadBalancer.servers]]
|
||||
url = "foobar"
|
||||
[http.services.Service0.loadBalancer.healthCheck]
|
||||
scheme = "foobar"
|
||||
path = "foobar"
|
||||
port = 42
|
||||
interval = "foobar"
|
||||
timeout = "foobar"
|
||||
hostname = "foobar"
|
||||
[http.services.Service0.loadBalancer.healthCheck.headers]
|
||||
name0 = "foobar"
|
||||
name1 = "foobar"
|
||||
[http.services.Service0.loadBalancer.responseForwarding]
|
||||
flushInterval = "foobar"
|
||||
|
||||
[tcp]
|
||||
[tcp.routers]
|
||||
[tcp.routers.TCPRouter0]
|
||||
entryPoints = ["foobar", "foobar"]
|
||||
service = "foobar"
|
||||
rule = "foobar"
|
||||
[tcp.routers.TCPRouter0.tls]
|
||||
passthrough = true
|
||||
[tcp.services]
|
||||
[tcp.services.TCPService0]
|
||||
[tcp.services.TCPService0.loadBalancer]
|
||||
|
||||
[[tcp.services.TCPService0.loadBalancer.servers]]
|
||||
address = "foobar"
|
||||
|
||||
[[tcp.services.TCPService0.loadBalancer.servers]]
|
||||
address = "foobar"
|
||||
|
||||
[tls]
|
||||
|
||||
[[tls.Certificates]]
|
||||
certFile = "foobar"
|
||||
keyFile = "foobar"
|
||||
stores = ["foobar", "foobar"]
|
||||
|
||||
[[tls.Certificates]]
|
||||
certFile = "foobar"
|
||||
keyFile = "foobar"
|
||||
stores = ["foobar", "foobar"]
|
||||
[tls.options]
|
||||
[tls.options.TLS0]
|
||||
minVersion = "foobar"
|
||||
cipherSuites = ["foobar", "foobar"]
|
||||
sniStrict = true
|
||||
[tls.options.TLS0.clientCA]
|
||||
files = ["foobar", "foobar"]
|
||||
optional = true
|
||||
[tls.options.TLS1]
|
||||
minVersion = "foobar"
|
||||
cipherSuites = ["foobar", "foobar"]
|
||||
sniStrict = true
|
||||
[tls.options.TLS1.clientCA]
|
||||
files = ["foobar", "foobar"]
|
||||
optional = true
|
||||
[tls.stores]
|
||||
[tls.stores.Store0]
|
||||
[tls.stores.Store0.defaultCertificate]
|
||||
certFile = "foobar"
|
||||
keyFile = "foobar"
|
||||
[tls.stores.Store1]
|
||||
[tls.stores.Store1.defaultCertificate]
|
||||
certFile = "foobar"
|
||||
keyFile = "foobar"
|
116
pkg/config/dynamic/http_config.go
Normal file
116
pkg/config/dynamic/http_config.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
package dynamic
|
||||
|
||||
import "reflect"
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// HTTPConfiguration contains all the HTTP configuration parameters.
|
||||
type HTTPConfiguration struct {
|
||||
Routers map[string]*Router `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty"`
|
||||
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
Services map[string]*Service `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Service holds a service configuration (can only be of one type at the same time).
|
||||
type Service struct {
|
||||
LoadBalancer *LoadBalancerService `json:"loadBalancer,omitempty" toml:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Router holds the router configuration.
|
||||
type Router struct {
|
||||
EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty"`
|
||||
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
||||
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
|
||||
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,omitempty"`
|
||||
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RouterTLSConfig holds the TLS configuration for a router
|
||||
type RouterTLSConfig struct {
|
||||
Options string `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// LoadBalancerService holds the LoadBalancerService configuration.
|
||||
type LoadBalancerService struct {
|
||||
Stickiness *Stickiness `json:"stickiness,omitempty" toml:"stickiness,omitempty" yaml:"stickiness,omitempty" label:"allowEmpty"`
|
||||
Servers []Server `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server"`
|
||||
HealthCheck *HealthCheck `json:"healthCheck,omitempty" toml:"healthCheck,omitempty" yaml:"healthCheck,omitempty"`
|
||||
PassHostHeader bool `json:"passHostHeader" toml:"passHostHeader" yaml:"passHostHeader"`
|
||||
ResponseForwarding *ResponseForwarding `json:"responseForwarding,omitempty" toml:"responseForwarding,omitempty" yaml:"responseForwarding,omitempty"`
|
||||
}
|
||||
|
||||
// Mergeable tells if the given service is mergeable.
|
||||
func (l *LoadBalancerService) Mergeable(loadBalancer *LoadBalancerService) bool {
|
||||
savedServers := l.Servers
|
||||
defer func() {
|
||||
l.Servers = savedServers
|
||||
}()
|
||||
l.Servers = nil
|
||||
|
||||
savedServersLB := loadBalancer.Servers
|
||||
defer func() {
|
||||
loadBalancer.Servers = savedServersLB
|
||||
}()
|
||||
loadBalancer.Servers = nil
|
||||
|
||||
return reflect.DeepEqual(l, loadBalancer)
|
||||
}
|
||||
|
||||
// SetDefaults Default values for a LoadBalancerService.
|
||||
func (l *LoadBalancerService) SetDefaults() {
|
||||
l.PassHostHeader = true
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ResponseForwarding holds configuration for the forward of the response.
|
||||
type ResponseForwarding struct {
|
||||
FlushInterval string `json:"flushInterval,omitempty" toml:"flushInterval,omitempty" yaml:"flushInterval,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Stickiness holds the stickiness configuration.
|
||||
type Stickiness struct {
|
||||
CookieName string `json:"cookieName,omitempty" toml:"cookieName,omitempty" yaml:"cookieName,omitempty"`
|
||||
SecureCookie bool `json:"secureCookie,omitempty" toml:"secureCookie,omitempty" yaml:"secureCookie,omitempty"`
|
||||
HTTPOnlyCookie bool `json:"httpOnlyCookie,omitempty" toml:"httpOnlyCookie,omitempty" yaml:"httpOnlyCookie,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Server holds the server configuration.
|
||||
type Server struct {
|
||||
URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"`
|
||||
Scheme string `toml:"-" json:"-" yaml:"-"`
|
||||
Port string `toml:"-" json:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
// SetDefaults Default values for a Server.
|
||||
func (s *Server) SetDefaults() {
|
||||
s.Scheme = "http"
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// HealthCheck holds the HealthCheck configuration.
|
||||
type HealthCheck struct {
|
||||
Scheme string `json:"scheme,omitempty" toml:"scheme,omitempty" yaml:"scheme,omitempty"`
|
||||
Path string `json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty"`
|
||||
Port int `json:"port,omitempty" toml:"port,omitempty,omitzero" yaml:"port,omitempty"`
|
||||
// FIXME change string to types.Duration
|
||||
Interval string `json:"interval,omitempty" toml:"interval,omitempty" yaml:"interval,omitempty"`
|
||||
// FIXME change string to types.Duration
|
||||
Timeout string `json:"timeout,omitempty" toml:"timeout,omitempty" yaml:"timeout,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty" toml:"hostname,omitempty" yaml:"hostname,omitempty"`
|
||||
Headers map[string]string `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
}
|
464
pkg/config/dynamic/middlewares.go
Normal file
464
pkg/config/dynamic/middlewares.go
Normal file
|
@ -0,0 +1,464 @@
|
|||
package dynamic
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/containous/traefik/pkg/ip"
|
||||
"github.com/containous/traefik/pkg/types"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Middleware holds the Middleware configuration.
|
||||
type Middleware struct {
|
||||
AddPrefix *AddPrefix `json:"addPrefix,omitempty" toml:"addPrefix,omitempty" yaml:"addPrefix,omitempty"`
|
||||
StripPrefix *StripPrefix `json:"stripPrefix,omitempty" toml:"stripPrefix,omitempty" yaml:"stripPrefix,omitempty"`
|
||||
StripPrefixRegex *StripPrefixRegex `json:"stripPrefixRegex,omitempty" toml:"stripPrefixRegex,omitempty" yaml:"stripPrefixRegex,omitempty"`
|
||||
ReplacePath *ReplacePath `json:"replacePath,omitempty" toml:"replacePath,omitempty" yaml:"replacePath,omitempty"`
|
||||
ReplacePathRegex *ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty"`
|
||||
Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty"`
|
||||
IPWhiteList *IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty"`
|
||||
Headers *Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Errors *ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty"`
|
||||
RateLimit *RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty"`
|
||||
RedirectRegex *RedirectRegex `json:"redirectRegex,omitempty" toml:"redirectRegex,omitempty" yaml:"redirectRegex,omitempty"`
|
||||
RedirectScheme *RedirectScheme `json:"redirectScheme,omitempty" toml:"redirectScheme,omitempty" yaml:"redirectScheme,omitempty"`
|
||||
BasicAuth *BasicAuth `json:"basicAuth,omitempty" toml:"basicAuth,omitempty" yaml:"basicAuth,omitempty"`
|
||||
DigestAuth *DigestAuth `json:"digestAuth,omitempty" toml:"digestAuth,omitempty" yaml:"digestAuth,omitempty"`
|
||||
ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty" toml:"forwardAuth,omitempty" yaml:"forwardAuth,omitempty"`
|
||||
MaxConn *MaxConn `json:"maxConn,omitempty" toml:"maxConn,omitempty" yaml:"maxConn,omitempty"`
|
||||
Buffering *Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"`
|
||||
CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"`
|
||||
Compress *Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty"`
|
||||
PassTLSClientCert *PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"`
|
||||
Retry *Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// AddPrefix holds the AddPrefix configuration.
|
||||
type AddPrefix struct {
|
||||
Prefix string `json:"prefix,omitempty" toml:"prefix,omitempty" yaml:"prefix,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Auth holds the authentication configuration (BASIC, DIGEST, users).
|
||||
type Auth struct {
|
||||
Basic *BasicAuth `json:"basic,omitempty" toml:"basic,omitempty" yaml:"basic,omitempty" export:"true"`
|
||||
Digest *DigestAuth `json:"digest,omitempty" toml:"digest,omitempty" yaml:"digest,omitempty" export:"true"`
|
||||
Forward *ForwardAuth `json:"forward,omitempty" toml:"forward,omitempty" yaml:"forward,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// BasicAuth holds the HTTP basic authentication configuration.
|
||||
type BasicAuth struct {
|
||||
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty"`
|
||||
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
|
||||
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
|
||||
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty"`
|
||||
HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Buffering holds the request/response buffering configuration.
|
||||
type Buffering struct {
|
||||
MaxRequestBodyBytes int64 `json:"maxRequestBodyBytes,omitempty" toml:"maxRequestBodyBytes,omitempty" yaml:"maxRequestBodyBytes,omitempty"`
|
||||
MemRequestBodyBytes int64 `json:"memRequestBodyBytes,omitempty" toml:"memRequestBodyBytes,omitempty" yaml:"memRequestBodyBytes,omitempty"`
|
||||
MaxResponseBodyBytes int64 `json:"maxResponseBodyBytes,omitempty" toml:"maxResponseBodyBytes,omitempty" yaml:"maxResponseBodyBytes,omitempty"`
|
||||
MemResponseBodyBytes int64 `json:"memResponseBodyBytes,omitempty" toml:"memResponseBodyBytes,omitempty" yaml:"memResponseBodyBytes,omitempty"`
|
||||
RetryExpression string `json:"retryExpression,omitempty" toml:"retryExpression,omitempty" yaml:"retryExpression,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Chain holds a chain of middlewares
|
||||
type Chain struct {
|
||||
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// CircuitBreaker holds the circuit breaker configuration.
|
||||
type CircuitBreaker struct {
|
||||
Expression string `json:"expression,omitempty" toml:"expression,omitempty" yaml:"expression,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Compress holds the compress configuration.
|
||||
type Compress struct{}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// DigestAuth holds the Digest HTTP authentication configuration.
|
||||
type DigestAuth struct {
|
||||
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty"`
|
||||
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
|
||||
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty"`
|
||||
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
|
||||
HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ErrorPage holds the custom error page configuration.
|
||||
type ErrorPage struct {
|
||||
Status []string `json:"status,omitempty" toml:"status,omitempty" yaml:"status,omitempty"`
|
||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
||||
Query string `json:"query,omitempty" toml:"query,omitempty" yaml:"query,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ForwardAuth holds the http forward authentication configuration.
|
||||
type ForwardAuth struct {
|
||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
||||
TLS *ClientTLS `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty"`
|
||||
TrustForwardHeader bool `json:"trustForwardHeader,omitempty" toml:"trustForwardHeader,omitempty" yaml:"trustForwardHeader,omitempty" export:"true"`
|
||||
AuthResponseHeaders []string `json:"authResponseHeaders,omitempty" toml:"authResponseHeaders,omitempty" yaml:"authResponseHeaders,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Headers holds the custom header configuration.
|
||||
type Headers struct {
|
||||
CustomRequestHeaders map[string]string `json:"customRequestHeaders,omitempty" toml:"customRequestHeaders,omitempty" yaml:"customRequestHeaders,omitempty"`
|
||||
CustomResponseHeaders map[string]string `json:"customResponseHeaders,omitempty" toml:"customResponseHeaders,omitempty" yaml:"customResponseHeaders,omitempty"`
|
||||
|
||||
// AccessControlAllowCredentials is only valid if true. false is ignored.
|
||||
AccessControlAllowCredentials bool `json:"accessControlAllowCredentials,omitempty" toml:"accessControlAllowCredentials,omitempty" yaml:"accessControlAllowCredentials,omitempty"`
|
||||
// AccessControlAllowHeaders must be used in response to a preflight request with Access-Control-Request-Headers set.
|
||||
AccessControlAllowHeaders []string `json:"accessControlAllowHeaders,omitempty" toml:"accessControlAllowHeaders,omitempty" yaml:"accessControlAllowHeaders,omitempty"`
|
||||
// AccessControlAllowMethods must be used in response to a preflight request with Access-Control-Request-Method set.
|
||||
AccessControlAllowMethods []string `json:"accessControlAllowMethods,omitempty" toml:"accessControlAllowMethods,omitempty" yaml:"accessControlAllowMethods,omitempty"`
|
||||
// AccessControlAllowOrigin Can be "origin-list-or-null" or "*". From (https://www.w3.org/TR/cors/#access-control-allow-origin-response-header)
|
||||
AccessControlAllowOrigin string `json:"accessControlAllowOrigin,omitempty" toml:"accessControlAllowOrigin,omitempty" yaml:"accessControlAllowOrigin,omitempty"`
|
||||
// AccessControlExposeHeaders sets valid headers for the response.
|
||||
AccessControlExposeHeaders []string `json:"accessControlExposeHeaders,omitempty" toml:"accessControlExposeHeaders,omitempty" yaml:"accessControlExposeHeaders,omitempty"`
|
||||
// AccessControlMaxAge sets the time that a preflight request may be cached.
|
||||
AccessControlMaxAge int64 `json:"accessControlMaxAge,omitempty" toml:"accessControlMaxAge,omitempty" yaml:"accessControlMaxAge,omitempty"`
|
||||
// AddVaryHeader controls if the Vary header is automatically added/updated when the AccessControlAllowOrigin is set.
|
||||
AddVaryHeader bool `json:"addVaryHeader,omitempty" toml:"addVaryHeader,omitempty" yaml:"addVaryHeader,omitempty"`
|
||||
|
||||
AllowedHosts []string `json:"allowedHosts,omitempty" toml:"allowedHosts,omitempty" yaml:"allowedHosts,omitempty"`
|
||||
HostsProxyHeaders []string `json:"hostsProxyHeaders,omitempty" toml:"hostsProxyHeaders,omitempty" yaml:"hostsProxyHeaders,omitempty"`
|
||||
SSLRedirect bool `json:"sslRedirect,omitempty" toml:"sslRedirect,omitempty" yaml:"sslRedirect,omitempty"`
|
||||
SSLTemporaryRedirect bool `json:"sslTemporaryRedirect,omitempty" toml:"sslTemporaryRedirect,omitempty" yaml:"sslTemporaryRedirect,omitempty"`
|
||||
SSLHost string `json:"sslHost,omitempty" toml:"sslHost,omitempty" yaml:"sslHost,omitempty"`
|
||||
SSLProxyHeaders map[string]string `json:"sslProxyHeaders,omitempty" toml:"sslProxyHeaders,omitempty" yaml:"sslProxyHeaders,omitempty"`
|
||||
SSLForceHost bool `json:"sslForceHost,omitempty" toml:"sslForceHost,omitempty" yaml:"sslForceHost,omitempty"`
|
||||
STSSeconds int64 `json:"stsSeconds,omitempty" toml:"stsSeconds,omitempty" yaml:"stsSeconds,omitempty"`
|
||||
STSIncludeSubdomains bool `json:"stsIncludeSubdomains,omitempty" toml:"stsIncludeSubdomains,omitempty" yaml:"stsIncludeSubdomains,omitempty"`
|
||||
STSPreload bool `json:"stsPreload,omitempty" toml:"stsPreload,omitempty" yaml:"stsPreload,omitempty"`
|
||||
ForceSTSHeader bool `json:"forceSTSHeader,omitempty" toml:"forceSTSHeader,omitempty" yaml:"forceSTSHeader,omitempty"`
|
||||
FrameDeny bool `json:"frameDeny,omitempty" toml:"frameDeny,omitempty" yaml:"frameDeny,omitempty"`
|
||||
CustomFrameOptionsValue string `json:"customFrameOptionsValue,omitempty" toml:"customFrameOptionsValue,omitempty" yaml:"customFrameOptionsValue,omitempty"`
|
||||
ContentTypeNosniff bool `json:"contentTypeNosniff,omitempty" toml:"contentTypeNosniff,omitempty" yaml:"contentTypeNosniff,omitempty"`
|
||||
BrowserXSSFilter bool `json:"browserXssFilter,omitempty" toml:"browserXssFilter,omitempty" yaml:"browserXssFilter,omitempty"`
|
||||
CustomBrowserXSSValue string `json:"customBrowserXSSValue,omitempty" toml:"customBrowserXSSValue,omitempty" yaml:"customBrowserXSSValue,omitempty"`
|
||||
ContentSecurityPolicy string `json:"contentSecurityPolicy,omitempty" toml:"contentSecurityPolicy,omitempty" yaml:"contentSecurityPolicy,omitempty"`
|
||||
PublicKey string `json:"publicKey,omitempty" toml:"publicKey,omitempty" yaml:"publicKey,omitempty"`
|
||||
ReferrerPolicy string `json:"referrerPolicy,omitempty" toml:"referrerPolicy,omitempty" yaml:"referrerPolicy,omitempty"`
|
||||
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty"`
|
||||
}
|
||||
|
||||
// HasCustomHeadersDefined checks to see if any of the custom header elements have been set
|
||||
func (h *Headers) HasCustomHeadersDefined() bool {
|
||||
return h != nil && (len(h.CustomResponseHeaders) != 0 ||
|
||||
len(h.CustomRequestHeaders) != 0)
|
||||
}
|
||||
|
||||
// HasCorsHeadersDefined checks to see if any of the cors header elements have been set
|
||||
func (h *Headers) HasCorsHeadersDefined() bool {
|
||||
return h != nil && (h.AccessControlAllowCredentials ||
|
||||
len(h.AccessControlAllowHeaders) != 0 ||
|
||||
len(h.AccessControlAllowMethods) != 0 ||
|
||||
h.AccessControlAllowOrigin != "" ||
|
||||
len(h.AccessControlExposeHeaders) != 0 ||
|
||||
h.AccessControlMaxAge != 0 ||
|
||||
h.AddVaryHeader)
|
||||
}
|
||||
|
||||
// HasSecureHeadersDefined checks to see if any of the secure header elements have been set
|
||||
func (h *Headers) HasSecureHeadersDefined() bool {
|
||||
return h != nil && (len(h.AllowedHosts) != 0 ||
|
||||
len(h.HostsProxyHeaders) != 0 ||
|
||||
h.SSLRedirect ||
|
||||
h.SSLTemporaryRedirect ||
|
||||
h.SSLForceHost ||
|
||||
h.SSLHost != "" ||
|
||||
len(h.SSLProxyHeaders) != 0 ||
|
||||
h.STSSeconds != 0 ||
|
||||
h.STSIncludeSubdomains ||
|
||||
h.STSPreload ||
|
||||
h.ForceSTSHeader ||
|
||||
h.FrameDeny ||
|
||||
h.CustomFrameOptionsValue != "" ||
|
||||
h.ContentTypeNosniff ||
|
||||
h.BrowserXSSFilter ||
|
||||
h.CustomBrowserXSSValue != "" ||
|
||||
h.ContentSecurityPolicy != "" ||
|
||||
h.PublicKey != "" ||
|
||||
h.ReferrerPolicy != "" ||
|
||||
h.IsDevelopment)
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// IPStrategy holds the ip strategy configuration.
|
||||
type IPStrategy struct {
|
||||
Depth int `json:"depth,omitempty" toml:"depth,omitempty" yaml:"depth,omitempty" export:"true"`
|
||||
ExcludedIPs []string `json:"excludedIPs,omitempty" toml:"excludedIPs,omitempty" yaml:"excludedIPs,omitempty"`
|
||||
}
|
||||
|
||||
// Get an IP selection strategy
|
||||
// if nil return the RemoteAddr strategy
|
||||
// else return a strategy base on the configuration using the X-Forwarded-For Header.
|
||||
// Depth override the ExcludedIPs
|
||||
func (s *IPStrategy) Get() (ip.Strategy, error) {
|
||||
if s == nil {
|
||||
return &ip.RemoteAddrStrategy{}, nil
|
||||
}
|
||||
|
||||
if s.Depth > 0 {
|
||||
return &ip.DepthStrategy{
|
||||
Depth: s.Depth,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if len(s.ExcludedIPs) > 0 {
|
||||
checker, err := ip.NewChecker(s.ExcludedIPs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ip.CheckerStrategy{
|
||||
Checker: checker,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &ip.RemoteAddrStrategy{}, nil
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// IPWhiteList holds the ip white list configuration.
|
||||
type IPWhiteList struct {
|
||||
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
||||
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// MaxConn holds maximum connection configuration.
|
||||
type MaxConn struct {
|
||||
Amount int64 `json:"amount,omitempty" toml:"amount,omitempty" yaml:"amount,omitempty"`
|
||||
ExtractorFunc string `json:"extractorFunc,omitempty" toml:"extractorFunc,omitempty" yaml:"extractorFunc,omitempty"`
|
||||
}
|
||||
|
||||
// SetDefaults Default values for a MaxConn.
|
||||
func (m *MaxConn) SetDefaults() {
|
||||
m.ExtractorFunc = "request.host"
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// PassTLSClientCert holds the TLS client cert headers configuration.
|
||||
type PassTLSClientCert struct {
|
||||
PEM bool `json:"pem,omitempty" toml:"pem,omitempty" yaml:"pem,omitempty"`
|
||||
Info *TLSClientCertificateInfo `json:"info,omitempty" toml:"info,omitempty" yaml:"info,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Rate holds the rate limiting configuration for a specific time period.
|
||||
type Rate struct {
|
||||
Period types.Duration `json:"period,omitempty" toml:"period,omitempty" yaml:"period,omitempty"`
|
||||
Average int64 `json:"average,omitempty" toml:"average,omitempty" yaml:"average,omitempty"`
|
||||
Burst int64 `json:"burst,omitempty" toml:"burst,omitempty" yaml:"burst,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RateLimit holds the rate limiting configuration for a given frontend.
|
||||
type RateLimit struct {
|
||||
RateSet map[string]*Rate `json:"rateSet,omitempty" toml:"rateSet,omitempty" yaml:"rateSet,omitempty"`
|
||||
// FIXME replace by ipStrategy see oxy and replace
|
||||
ExtractorFunc string `json:"extractorFunc,omitempty" toml:"extractorFunc,omitempty" yaml:"extractorFunc,omitempty"`
|
||||
}
|
||||
|
||||
// SetDefaults Default values for a MaxConn.
|
||||
func (r *RateLimit) SetDefaults() {
|
||||
r.ExtractorFunc = "request.host"
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RedirectRegex holds the redirection configuration.
|
||||
type RedirectRegex struct {
|
||||
Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty"`
|
||||
Replacement string `json:"replacement,omitempty" toml:"replacement,omitempty" yaml:"replacement,omitempty"`
|
||||
Permanent bool `json:"permanent,omitempty" toml:"permanent,omitempty" yaml:"permanent,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RedirectScheme holds the scheme redirection configuration.
|
||||
type RedirectScheme struct {
|
||||
Scheme string `json:"scheme,omitempty" toml:"scheme,omitempty" yaml:"scheme,omitempty"`
|
||||
Port string `json:"port,omitempty" toml:"port,omitempty" yaml:"port,omitempty"`
|
||||
Permanent bool `json:"permanent,omitempty" toml:"permanent,omitempty" yaml:"permanent,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ReplacePath holds the ReplacePath configuration.
|
||||
type ReplacePath struct {
|
||||
Path string `json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ReplacePathRegex holds the ReplacePathRegex configuration.
|
||||
type ReplacePathRegex struct {
|
||||
Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty"`
|
||||
Replacement string `json:"replacement,omitempty" toml:"replacement,omitempty" yaml:"replacement,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Retry holds the retry configuration.
|
||||
type Retry struct {
|
||||
Attempts int `json:"attempts,omitempty" toml:"attempts,omitempty" yaml:"attempts,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// StripPrefix holds the StripPrefix configuration.
|
||||
type StripPrefix struct {
|
||||
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// StripPrefixRegex holds the StripPrefixRegex configuration.
|
||||
type StripPrefixRegex struct {
|
||||
Regex []string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TLSClientCertificateInfo holds the client TLS certificate info configuration.
|
||||
type TLSClientCertificateInfo struct {
|
||||
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty"`
|
||||
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty"`
|
||||
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty"`
|
||||
Subject *TLSCLientCertificateDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty"`
|
||||
Issuer *TLSCLientCertificateDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TLSCLientCertificateDNInfo holds the client TLS certificate distinguished name info configuration
|
||||
// cf https://tools.ietf.org/html/rfc3739
|
||||
type TLSCLientCertificateDNInfo struct {
|
||||
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty"`
|
||||
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty"`
|
||||
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty"`
|
||||
Organization bool `json:"organization,omitempty" toml:"organization,omitempty" yaml:"organization,omitempty"`
|
||||
CommonName bool `json:"commonName,omitempty" toml:"commonName,omitempty" yaml:"commonName,omitempty"`
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty"`
|
||||
DomainComponent bool `json:"domainComponent,omitempty" toml:"domainComponent,omitempty" yaml:"domainComponent,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Users holds a list of users
|
||||
type Users []string
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ClientTLS holds the TLS specific configurations as client
|
||||
// CA, Cert and Key can be either path or file contents.
|
||||
type ClientTLS struct {
|
||||
CA string `json:"ca,omitempty" toml:"ca,omitempty" yaml:"ca,omitempty"`
|
||||
CAOptional bool `json:"caOptional,omitempty" toml:"caOptional,omitempty" yaml:"caOptional,omitempty"`
|
||||
Cert string `json:"cert,omitempty" toml:"cert,omitempty" yaml:"cert,omitempty"`
|
||||
Key string `json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty"`
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty"`
|
||||
}
|
||||
|
||||
// CreateTLSConfig creates a TLS config from ClientTLS structures.
|
||||
func (clientTLS *ClientTLS) CreateTLSConfig() (*tls.Config, error) {
|
||||
if clientTLS == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
caPool := x509.NewCertPool()
|
||||
clientAuth := tls.NoClientCert
|
||||
if clientTLS.CA != "" {
|
||||
var ca []byte
|
||||
if _, errCA := os.Stat(clientTLS.CA); errCA == nil {
|
||||
ca, err = ioutil.ReadFile(clientTLS.CA)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read CA. %s", err)
|
||||
}
|
||||
} else {
|
||||
ca = []byte(clientTLS.CA)
|
||||
}
|
||||
|
||||
if !caPool.AppendCertsFromPEM(ca) {
|
||||
return nil, fmt.Errorf("failed to parse CA")
|
||||
}
|
||||
|
||||
if clientTLS.CAOptional {
|
||||
clientAuth = tls.VerifyClientCertIfGiven
|
||||
} else {
|
||||
clientAuth = tls.RequireAndVerifyClientCert
|
||||
}
|
||||
}
|
||||
|
||||
cert := tls.Certificate{}
|
||||
_, errKeyIsFile := os.Stat(clientTLS.Key)
|
||||
|
||||
if !clientTLS.InsecureSkipVerify && (len(clientTLS.Cert) == 0 || len(clientTLS.Key) == 0) {
|
||||
return nil, fmt.Errorf("TLS Certificate or Key file must be set when TLS configuration is created")
|
||||
}
|
||||
|
||||
if len(clientTLS.Cert) > 0 && len(clientTLS.Key) > 0 {
|
||||
if _, errCertIsFile := os.Stat(clientTLS.Cert); errCertIsFile == nil {
|
||||
if errKeyIsFile == nil {
|
||||
cert, err = tls.LoadX509KeyPair(clientTLS.Cert, clientTLS.Key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load TLS keypair: %v", err)
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("tls cert is a file, but tls key is not")
|
||||
}
|
||||
} else {
|
||||
if errKeyIsFile != nil {
|
||||
cert, err = tls.X509KeyPair([]byte(clientTLS.Cert), []byte(clientTLS.Key))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load TLS keypair: %v", err)
|
||||
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("TLS key is a file, but tls cert is not")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caPool,
|
||||
InsecureSkipVerify: clientTLS.InsecureSkipVerify,
|
||||
ClientAuth: clientAuth,
|
||||
}, nil
|
||||
}
|
279
pkg/config/dynamic/runtime.go
Normal file
279
pkg/config/dynamic/runtime.go
Normal file
|
@ -0,0 +1,279 @@
|
|||
package dynamic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containous/traefik/pkg/log"
|
||||
)
|
||||
|
||||
// RuntimeConfiguration holds the information about the currently running traefik instance.
|
||||
type RuntimeConfiguration struct {
|
||||
Routers map[string]*RouterInfo `json:"routers,omitempty"`
|
||||
Middlewares map[string]*MiddlewareInfo `json:"middlewares,omitempty"`
|
||||
Services map[string]*ServiceInfo `json:"services,omitempty"`
|
||||
TCPRouters map[string]*TCPRouterInfo `json:"tcpRouters,omitempty"`
|
||||
TCPServices map[string]*TCPServiceInfo `json:"tcpServices,omitempty"`
|
||||
}
|
||||
|
||||
// NewRuntimeConfig returns a RuntimeConfiguration initialized with the given conf. It never returns nil.
|
||||
func NewRuntimeConfig(conf Configuration) *RuntimeConfiguration {
|
||||
if conf.HTTP == nil && conf.TCP == nil {
|
||||
return &RuntimeConfiguration{}
|
||||
}
|
||||
|
||||
runtimeConfig := &RuntimeConfiguration{}
|
||||
|
||||
if conf.HTTP != nil {
|
||||
routers := conf.HTTP.Routers
|
||||
if len(routers) > 0 {
|
||||
runtimeConfig.Routers = make(map[string]*RouterInfo, len(routers))
|
||||
for k, v := range routers {
|
||||
runtimeConfig.Routers[k] = &RouterInfo{Router: v}
|
||||
}
|
||||
}
|
||||
|
||||
services := conf.HTTP.Services
|
||||
if len(services) > 0 {
|
||||
runtimeConfig.Services = make(map[string]*ServiceInfo, len(services))
|
||||
for k, v := range services {
|
||||
runtimeConfig.Services[k] = &ServiceInfo{Service: v}
|
||||
}
|
||||
}
|
||||
|
||||
middlewares := conf.HTTP.Middlewares
|
||||
if len(middlewares) > 0 {
|
||||
runtimeConfig.Middlewares = make(map[string]*MiddlewareInfo, len(middlewares))
|
||||
for k, v := range middlewares {
|
||||
runtimeConfig.Middlewares[k] = &MiddlewareInfo{Middleware: v}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if conf.TCP != nil {
|
||||
if len(conf.TCP.Routers) > 0 {
|
||||
runtimeConfig.TCPRouters = make(map[string]*TCPRouterInfo, len(conf.TCP.Routers))
|
||||
for k, v := range conf.TCP.Routers {
|
||||
runtimeConfig.TCPRouters[k] = &TCPRouterInfo{TCPRouter: v}
|
||||
}
|
||||
}
|
||||
|
||||
if len(conf.TCP.Services) > 0 {
|
||||
runtimeConfig.TCPServices = make(map[string]*TCPServiceInfo, len(conf.TCP.Services))
|
||||
for k, v := range conf.TCP.Services {
|
||||
runtimeConfig.TCPServices[k] = &TCPServiceInfo{TCPService: v}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return runtimeConfig
|
||||
}
|
||||
|
||||
// PopulateUsedBy populates all the UsedBy lists of the underlying fields of r,
|
||||
// based on the relations between the included services, routers, and middlewares.
|
||||
func (r *RuntimeConfiguration) PopulateUsedBy() {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
logger := log.WithoutContext()
|
||||
|
||||
for routerName, routerInfo := range r.Routers {
|
||||
providerName := getProviderName(routerName)
|
||||
if providerName == "" {
|
||||
logger.WithField(log.RouterName, routerName).Error("router name is not fully qualified")
|
||||
continue
|
||||
}
|
||||
|
||||
for _, midName := range routerInfo.Router.Middlewares {
|
||||
fullMidName := getQualifiedName(providerName, midName)
|
||||
if _, ok := r.Middlewares[fullMidName]; !ok {
|
||||
continue
|
||||
}
|
||||
r.Middlewares[fullMidName].UsedBy = append(r.Middlewares[fullMidName].UsedBy, routerName)
|
||||
}
|
||||
|
||||
serviceName := getQualifiedName(providerName, routerInfo.Router.Service)
|
||||
if _, ok := r.Services[serviceName]; !ok {
|
||||
continue
|
||||
}
|
||||
r.Services[serviceName].UsedBy = append(r.Services[serviceName].UsedBy, routerName)
|
||||
}
|
||||
|
||||
for k := range r.Services {
|
||||
sort.Strings(r.Services[k].UsedBy)
|
||||
}
|
||||
|
||||
for k := range r.Middlewares {
|
||||
sort.Strings(r.Middlewares[k].UsedBy)
|
||||
}
|
||||
|
||||
for routerName, routerInfo := range r.TCPRouters {
|
||||
providerName := getProviderName(routerName)
|
||||
if providerName == "" {
|
||||
logger.WithField(log.RouterName, routerName).Error("tcp router name is not fully qualified")
|
||||
continue
|
||||
}
|
||||
|
||||
serviceName := getQualifiedName(providerName, routerInfo.TCPRouter.Service)
|
||||
if _, ok := r.TCPServices[serviceName]; !ok {
|
||||
continue
|
||||
}
|
||||
r.TCPServices[serviceName].UsedBy = append(r.TCPServices[serviceName].UsedBy, routerName)
|
||||
}
|
||||
|
||||
for k := range r.TCPServices {
|
||||
sort.Strings(r.TCPServices[k].UsedBy)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(entryPoints []string, entryPointName string) bool {
|
||||
for _, name := range entryPoints {
|
||||
if name == entryPointName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetRoutersByEntrypoints returns all the http routers by entrypoints name and routers name
|
||||
func (r *RuntimeConfiguration) GetRoutersByEntrypoints(ctx context.Context, entryPoints []string, tls bool) map[string]map[string]*RouterInfo {
|
||||
entryPointsRouters := make(map[string]map[string]*RouterInfo)
|
||||
|
||||
for rtName, rt := range r.Routers {
|
||||
if (tls && rt.TLS == nil) || (!tls && rt.TLS != nil) {
|
||||
continue
|
||||
}
|
||||
|
||||
eps := rt.EntryPoints
|
||||
if len(eps) == 0 {
|
||||
eps = entryPoints
|
||||
}
|
||||
for _, entryPointName := range eps {
|
||||
if !contains(entryPoints, entryPointName) {
|
||||
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
|
||||
Errorf("entryPoint %q doesn't exist", entryPointName)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := entryPointsRouters[entryPointName]; !ok {
|
||||
entryPointsRouters[entryPointName] = make(map[string]*RouterInfo)
|
||||
}
|
||||
|
||||
entryPointsRouters[entryPointName][rtName] = rt
|
||||
}
|
||||
}
|
||||
|
||||
return entryPointsRouters
|
||||
}
|
||||
|
||||
// GetTCPRoutersByEntrypoints returns all the tcp routers by entrypoints name and routers name
|
||||
func (r *RuntimeConfiguration) GetTCPRoutersByEntrypoints(ctx context.Context, entryPoints []string) map[string]map[string]*TCPRouterInfo {
|
||||
entryPointsRouters := make(map[string]map[string]*TCPRouterInfo)
|
||||
|
||||
for rtName, rt := range r.TCPRouters {
|
||||
eps := rt.EntryPoints
|
||||
if len(eps) == 0 {
|
||||
eps = entryPoints
|
||||
}
|
||||
|
||||
for _, entryPointName := range eps {
|
||||
if !contains(entryPoints, entryPointName) {
|
||||
log.FromContext(log.With(ctx, log.Str(log.EntryPointName, entryPointName))).
|
||||
Errorf("entryPoint %q doesn't exist", entryPointName)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := entryPointsRouters[entryPointName]; !ok {
|
||||
entryPointsRouters[entryPointName] = make(map[string]*TCPRouterInfo)
|
||||
}
|
||||
|
||||
entryPointsRouters[entryPointName][rtName] = rt
|
||||
}
|
||||
}
|
||||
|
||||
return entryPointsRouters
|
||||
}
|
||||
|
||||
// RouterInfo holds information about a currently running HTTP router
|
||||
type RouterInfo struct {
|
||||
*Router // dynamic configuration
|
||||
Err string `json:"error,omitempty"` // initialization error
|
||||
}
|
||||
|
||||
// TCPRouterInfo holds information about a currently running TCP router
|
||||
type TCPRouterInfo struct {
|
||||
*TCPRouter // dynamic configuration
|
||||
Err string `json:"error,omitempty"` // initialization error
|
||||
}
|
||||
|
||||
// MiddlewareInfo holds information about a currently running middleware
|
||||
type MiddlewareInfo struct {
|
||||
*Middleware // dynamic configuration
|
||||
Err error `json:"error,omitempty"` // initialization error
|
||||
UsedBy []string `json:"usedBy,omitempty"` // list of routers and services using that middleware
|
||||
}
|
||||
|
||||
// ServiceInfo holds information about a currently running service
|
||||
type ServiceInfo struct {
|
||||
*Service // dynamic configuration
|
||||
Err error `json:"error,omitempty"` // initialization error
|
||||
UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service
|
||||
|
||||
statusMu sync.RWMutex
|
||||
status map[string]string // keyed by server URL
|
||||
}
|
||||
|
||||
// UpdateStatus sets the status of the server in the ServiceInfo.
|
||||
// It is the responsibility of the caller to check that s is not nil.
|
||||
func (s *ServiceInfo) UpdateStatus(server string, status string) {
|
||||
s.statusMu.Lock()
|
||||
defer s.statusMu.Unlock()
|
||||
|
||||
if s.status == nil {
|
||||
s.status = make(map[string]string)
|
||||
}
|
||||
s.status[server] = status
|
||||
}
|
||||
|
||||
// GetAllStatus returns all the statuses of all the servers in ServiceInfo.
|
||||
// It is the responsibility of the caller to check that s is not nil
|
||||
func (s *ServiceInfo) GetAllStatus() map[string]string {
|
||||
s.statusMu.RLock()
|
||||
defer s.statusMu.RUnlock()
|
||||
|
||||
if len(s.status) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
allStatus := make(map[string]string, len(s.status))
|
||||
for k, v := range s.status {
|
||||
allStatus[k] = v
|
||||
}
|
||||
return allStatus
|
||||
}
|
||||
|
||||
// TCPServiceInfo holds information about a currently running TCP service
|
||||
type TCPServiceInfo struct {
|
||||
*TCPService // dynamic configuration
|
||||
Err error `json:"error,omitempty"` // initialization error
|
||||
UsedBy []string `json:"usedBy,omitempty"` // list of routers using that service
|
||||
}
|
||||
|
||||
func getProviderName(elementName string) string {
|
||||
parts := strings.Split(elementName, "@")
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getQualifiedName(provider, elementName string) string {
|
||||
parts := strings.Split(elementName, "@")
|
||||
if len(parts) == 1 {
|
||||
return elementName + "@" + provider
|
||||
}
|
||||
return elementName
|
||||
}
|
1087
pkg/config/dynamic/runtime_test.go
Normal file
1087
pkg/config/dynamic/runtime_test.go
Normal file
File diff suppressed because it is too large
Load diff
68
pkg/config/dynamic/tcp_config.go
Normal file
68
pkg/config/dynamic/tcp_config.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package dynamic
|
||||
|
||||
import "reflect"
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPConfiguration contains all the TCP configuration parameters.
|
||||
type TCPConfiguration struct {
|
||||
Routers map[string]*TCPRouter `json:"routers,omitempty" toml:"routers,omitempty" yaml:"routers,omitempty"`
|
||||
Services map[string]*TCPService `json:"services,omitempty" toml:"services,omitempty" yaml:"services,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPService holds a tcp service configuration (can only be of one type at the same time).
|
||||
type TCPService struct {
|
||||
LoadBalancer *TCPLoadBalancerService `json:"loadBalancer,omitempty" toml:"loadBalancer,omitempty" yaml:"loadBalancer,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPRouter holds the router configuration.
|
||||
type TCPRouter struct {
|
||||
EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty"`
|
||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
||||
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
|
||||
TLS *RouterTCPTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RouterTCPTLSConfig holds the TLS configuration for a router
|
||||
type RouterTCPTLSConfig struct {
|
||||
Passthrough bool `json:"passthrough" toml:"passthrough" yaml:"passthrough"`
|
||||
Options string `json:"options,omitempty" toml:"options,omitempty" yaml:"options,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPLoadBalancerService holds the LoadBalancerService configuration.
|
||||
type TCPLoadBalancerService struct {
|
||||
Servers []TCPServer `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server" label-slice-as-struct:"server"`
|
||||
}
|
||||
|
||||
// Mergeable tells if the given service is mergeable.
|
||||
func (l *TCPLoadBalancerService) Mergeable(loadBalancer *TCPLoadBalancerService) bool {
|
||||
savedServers := l.Servers
|
||||
defer func() {
|
||||
l.Servers = savedServers
|
||||
}()
|
||||
l.Servers = nil
|
||||
|
||||
savedServersLB := loadBalancer.Servers
|
||||
defer func() {
|
||||
loadBalancer.Servers = savedServersLB
|
||||
}()
|
||||
loadBalancer.Servers = nil
|
||||
|
||||
return reflect.DeepEqual(l, loadBalancer)
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPServer holds a TCP Server configuration
|
||||
type TCPServer struct {
|
||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
|
||||
Port string `toml:"-" json:"-" yaml:"-"`
|
||||
}
|
1257
pkg/config/dynamic/zz_generated.deepcopy.go
Normal file
1257
pkg/config/dynamic/zz_generated.deepcopy.go
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue