feat(kv): constants and generic methods.
This commit is contained in:
parent
61ecb4cd18
commit
6573634012
3 changed files with 228 additions and 10 deletions
|
@ -4,19 +4,68 @@ const (
|
||||||
pathBackends = "/backends/"
|
pathBackends = "/backends/"
|
||||||
pathBackendCircuitBreakerExpression = "/circuitbreaker/expression"
|
pathBackendCircuitBreakerExpression = "/circuitbreaker/expression"
|
||||||
pathBackendHealthCheckPath = "/healthcheck/path"
|
pathBackendHealthCheckPath = "/healthcheck/path"
|
||||||
|
pathBackendHealthCheckPort = "/healthcheck/port"
|
||||||
pathBackendHealthCheckInterval = "/healthcheck/interval"
|
pathBackendHealthCheckInterval = "/healthcheck/interval"
|
||||||
pathBackendLoadBalancerMethod = "/loadbalancer/method"
|
pathBackendLoadBalancerMethod = "/loadbalancer/method"
|
||||||
pathBackendLoadBalancerSticky = "/loadbalancer/sticky"
|
pathBackendLoadBalancerSticky = "/loadbalancer/sticky"
|
||||||
pathBackendLoadBalancerStickiness = "/loadbalancer/stickiness"
|
pathBackendLoadBalancerStickiness = "/loadbalancer/stickiness"
|
||||||
pathBackendLoadBalancerStickinessCookieName = "/loadbalancer/stickiness/cookiename"
|
pathBackendLoadBalancerStickinessCookieName = "/loadbalancer/stickiness/cookiename"
|
||||||
|
pathBackendMaxConnAmount = "/maxconn/amount"
|
||||||
|
pathBackendMaxConnExtractorFunc = "/maxconn/extractorfunc"
|
||||||
pathBackendServers = "/servers/"
|
pathBackendServers = "/servers/"
|
||||||
pathBackendServerURL = "/url"
|
pathBackendServerURL = "/url"
|
||||||
|
pathBackendServerWeight = "/weight"
|
||||||
|
|
||||||
pathFrontends = "/frontends/"
|
pathFrontends = "/frontends/"
|
||||||
pathFrontendBackend = "/backend"
|
pathFrontendBackend = "/backend"
|
||||||
pathFrontendPriority = "/priority"
|
pathFrontendPriority = "/priority"
|
||||||
pathFrontendPassHostHeader = "/passHostHeader"
|
pathFrontendPassHostHeader = "/passHostHeader"
|
||||||
pathFrontendEntryPoints = "/entrypoints"
|
pathFrontendPassTLSCert = "/passtlscert"
|
||||||
|
pathFrontendWhiteListSourceRange = "/whitelistsourcerange"
|
||||||
|
pathFrontendBasicAuth = "/basicauth"
|
||||||
|
pathFrontendEntryPoints = "/entrypoints"
|
||||||
|
pathFrontendRedirectEntryPoint = "/redirect/entrypoint"
|
||||||
|
pathFrontendRedirectRegex = "/redirect/regex"
|
||||||
|
pathFrontendRedirectReplacement = "/redirect/replacement"
|
||||||
|
pathFrontendErrorPages = "/errors/"
|
||||||
|
pathFrontendErrorPagesBackend = "/backend"
|
||||||
|
pathFrontendErrorPagesQuery = "/query"
|
||||||
|
pathFrontendErrorPagesStatus = "/status"
|
||||||
|
pathFrontendRateLimit = "/ratelimit/"
|
||||||
|
pathFrontendRateLimitRateSet = pathFrontendRateLimit + "rateset/"
|
||||||
|
pathFrontendRateLimitExtractorFunc = pathFrontendRateLimit + "extractorfunc"
|
||||||
|
pathFrontendRateLimitPeriod = "/period"
|
||||||
|
pathFrontendRateLimitAverage = "/average"
|
||||||
|
pathFrontendRateLimitBurst = "/burst"
|
||||||
|
|
||||||
|
pathFrontendCustomRequestHeaders = "/headers/customrequestheaders/"
|
||||||
|
pathFrontendCustomResponseHeaders = "/headers/customresponseheaders/"
|
||||||
|
pathFrontendAllowedHosts = "/headers/allowedhosts"
|
||||||
|
pathFrontendHostsProxyHeaders = "/headers/hostsproxyheaders"
|
||||||
|
pathFrontendSSLRedirect = "/headers/sslredirect"
|
||||||
|
pathFrontendSSLTemporaryRedirect = "/headers/ssltemporaryredirect"
|
||||||
|
pathFrontendSSLHost = "/headers/sslhost"
|
||||||
|
pathFrontendSSLProxyHeaders = "/headers/sslproxyheaders/"
|
||||||
|
pathFrontendSTSSeconds = "/headers/stsseconds"
|
||||||
|
pathFrontendSTSIncludeSubdomains = "/headers/stsincludesubdomains"
|
||||||
|
pathFrontendSTSPreload = "/headers/stspreload"
|
||||||
|
pathFrontendForceSTSHeader = "/headers/forcestsheader"
|
||||||
|
pathFrontendFrameDeny = "/headers/framedeny"
|
||||||
|
pathFrontendCustomFrameOptionsValue = "/headers/customframeoptionsvalue"
|
||||||
|
pathFrontendContentTypeNosniff = "/headers/contenttypenosniff"
|
||||||
|
pathFrontendBrowserXSSFilter = "/headers/browserxssfilter"
|
||||||
|
pathFrontendContentSecurityPolicy = "/headers/contentsecuritypolicy"
|
||||||
|
pathFrontendPublicKey = "/headers/publickey"
|
||||||
|
pathFrontendReferrerPolicy = "/headers/referrerpolicy"
|
||||||
|
pathFrontendIsDevelopment = "/headers/isdevelopment"
|
||||||
|
|
||||||
|
pathFrontendRoutes = "/routes/"
|
||||||
|
pathFrontendRule = "/rule"
|
||||||
|
|
||||||
|
pathTLSConfiguration = "/tlsconfiguration/"
|
||||||
|
pathTLSConfigurationEntryPoints = "/entrypoints"
|
||||||
|
pathTLSConfigurationCertFile = "/certificate/certfile"
|
||||||
|
pathTLSConfigurationKeyFile = "/certificate/keyfile"
|
||||||
|
|
||||||
pathTags = "/tags"
|
pathTags = "/tags"
|
||||||
pathAlias = "/alias"
|
pathAlias = "/alias"
|
||||||
|
|
|
@ -26,8 +26,12 @@ func (p *Provider) buildConfiguration() *types.Configuration {
|
||||||
"List": p.list,
|
"List": p.list,
|
||||||
"ListServers": p.listServers,
|
"ListServers": p.listServers,
|
||||||
"Get": p.get,
|
"Get": p.get,
|
||||||
|
"GetBool": p.getBool,
|
||||||
|
"GetInt": p.getInt,
|
||||||
|
"GetInt64": p.getInt64,
|
||||||
"SplitGet": p.splitGet,
|
"SplitGet": p.splitGet,
|
||||||
"Last": p.last,
|
"Last": p.last,
|
||||||
|
"Has": p.has,
|
||||||
|
|
||||||
// Backend functions
|
// Backend functions
|
||||||
"getSticky": p.getSticky,
|
"getSticky": p.getSticky,
|
||||||
|
@ -143,6 +147,41 @@ func (p *Provider) getBool(defaultValue bool, keyParts ...string) bool {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) has(keyParts ...string) bool {
|
||||||
|
value := p.get("", keyParts...)
|
||||||
|
return len(value) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getInt(defaultValue int, keyParts ...string) int {
|
||||||
|
rawValue := p.get("", keyParts...)
|
||||||
|
|
||||||
|
if len(rawValue) == 0 {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := strconv.Atoi(rawValue)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Invalid value for %v: %s", keyParts, rawValue)
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) getInt64(defaultValue int64, keyParts ...string) int64 {
|
||||||
|
rawValue := p.get("", keyParts...)
|
||||||
|
|
||||||
|
if len(rawValue) == 0 {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := strconv.ParseInt(rawValue, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Invalid value for %v: %s", keyParts, rawValue)
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) list(keyParts ...string) []string {
|
func (p *Provider) list(keyParts ...string) []string {
|
||||||
rootKey := strings.Join(keyParts, "")
|
rootKey := strings.Join(keyParts, "")
|
||||||
|
|
||||||
|
|
|
@ -62,16 +62,16 @@ func TestProviderBuildConfiguration(t *testing.T) {
|
||||||
desc: "all parameters",
|
desc: "all parameters",
|
||||||
kvPairs: filler("traefik",
|
kvPairs: filler("traefik",
|
||||||
backend("backend1",
|
backend("backend1",
|
||||||
withPair("healthcheck/path", "/health"),
|
|
||||||
withPair("healthcheck/port", "80"),
|
|
||||||
withPair("healthcheck/interval", "30s"),
|
|
||||||
withPair("maxconn/amount", "5"),
|
|
||||||
withPair("maxconn/extractorfunc", "client.ip"),
|
|
||||||
withPair(pathBackendCircuitBreakerExpression, label.DefaultCircuitBreakerExpression),
|
withPair(pathBackendCircuitBreakerExpression, label.DefaultCircuitBreakerExpression),
|
||||||
withPair(pathBackendLoadBalancerMethod, "drr"),
|
withPair(pathBackendLoadBalancerMethod, "drr"),
|
||||||
withPair(pathBackendLoadBalancerSticky, "true"),
|
withPair(pathBackendLoadBalancerSticky, "true"),
|
||||||
withPair(pathBackendLoadBalancerStickiness, "true"),
|
withPair(pathBackendLoadBalancerStickiness, "true"),
|
||||||
withPair(pathBackendLoadBalancerStickinessCookieName, "tomate"),
|
withPair(pathBackendLoadBalancerStickinessCookieName, "tomate"),
|
||||||
|
withPair(pathBackendHealthCheckPath, "/health"),
|
||||||
|
withPair(pathBackendHealthCheckPort, "80"),
|
||||||
|
withPair(pathBackendHealthCheckInterval, "30s"),
|
||||||
|
withPair(pathBackendMaxConnAmount, "5"),
|
||||||
|
withPair(pathBackendMaxConnExtractorFunc, "client.ip"),
|
||||||
withPair("servers/server1/url", "http://172.17.0.2:80"),
|
withPair("servers/server1/url", "http://172.17.0.2:80"),
|
||||||
withPair("servers/server1/weight", "0"),
|
withPair("servers/server1/weight", "0"),
|
||||||
withPair("servers/server2/weight", "0")),
|
withPair("servers/server2/weight", "0")),
|
||||||
|
@ -525,6 +525,136 @@ func TestProviderGetBool(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProviderGetInt(t *testing.T) {
|
||||||
|
defaultValue := 666
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
kvError error
|
||||||
|
keyParts []string
|
||||||
|
expected int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when has value",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair("bar", "6"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when empty value",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair("bar", ""),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: defaultValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when not existing key",
|
||||||
|
kvPairs: nil,
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: defaultValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when KV error",
|
||||||
|
kvError: store.ErrNotReachable,
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair("bar", "true"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: defaultValue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := &Provider{
|
||||||
|
kvClient: newKvClientMock(test.kvPairs, test.kvError),
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := p.getInt(defaultValue, test.keyParts...)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, actual, "key: %v", test.keyParts)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderGetInt64(t *testing.T) {
|
||||||
|
var defaultValue int64 = 666
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
desc string
|
||||||
|
kvPairs []*store.KVPair
|
||||||
|
kvError error
|
||||||
|
keyParts []string
|
||||||
|
expected int64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
desc: "when has value",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair("bar", "6"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when empty value",
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair("bar", ""),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: defaultValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when not existing key",
|
||||||
|
kvPairs: nil,
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: defaultValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "when KV error",
|
||||||
|
kvError: store.ErrNotReachable,
|
||||||
|
kvPairs: filler("traefik",
|
||||||
|
frontend("foo",
|
||||||
|
withPair("bar", "true"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyParts: []string{"traefik/frontends/foo/bar"},
|
||||||
|
expected: defaultValue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range testCases {
|
||||||
|
test := test
|
||||||
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
p := &Provider{
|
||||||
|
kvClient: newKvClientMock(test.kvPairs, test.kvError),
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := p.getInt64(defaultValue, test.keyParts...)
|
||||||
|
|
||||||
|
assert.Equal(t, test.expected, actual, "key: %v", test.keyParts)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProviderHasStickinessLabel(t *testing.T) {
|
func TestProviderHasStickinessLabel(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|
Loading…
Reference in a new issue