feat: use parser to load dynamic config from file.
This commit is contained in:
parent
7affeae480
commit
cb1d0441e9
27 changed files with 187 additions and 88 deletions
|
@ -302,3 +302,9 @@ providers:
|
||||||
--entryPoints.websecure.address=:443
|
--entryPoints.websecure.address=:443
|
||||||
--providers.kubernetesIngress=true
|
--providers.kubernetesIngress=true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## v2.2 to v2.3
|
||||||
|
|
||||||
|
### File Provider
|
||||||
|
|
||||||
|
The file parser has been changed, since v2.3 the unknown options/fields in a dynamic configuration file are treated as errors.
|
||||||
|
|
|
@ -238,7 +238,7 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
|
||||||
[[tls.certificates]]
|
[[tls.certificates]]
|
||||||
certFile = "/etc/traefik/cert-{{ $e }}.pem"
|
certFile = "/etc/traefik/cert-{{ $e }}.pem"
|
||||||
keyFile = "/etc/traefik/cert-{{ $e }}.key"
|
keyFile = "/etc/traefik/cert-{{ $e }}.key"
|
||||||
store = ["my-store-foo-{{ $e }}", "my-store-bar-{{ $e }}"]
|
stores = ["my-store-foo-{{ $e }}", "my-store-bar-{{ $e }}"]
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
[tls.config]
|
[tls.config]
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
[http.routers.test.tls]
|
[http.routers.test.tls]
|
||||||
|
|
||||||
[[tls.certificates]]
|
[[tls.certificates]]
|
||||||
store = ["default"]
|
stores = ["default"]
|
||||||
certFile = "fixtures/acme/ssl/wildcard.crt"
|
certFile = "fixtures/acme/ssl/wildcard.crt"
|
||||||
keyFile = "fixtures/acme/ssl/wildcard.key"
|
keyFile = "fixtures/acme/ssl/wildcard.key"
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
[http.routers.my-router]
|
[http.routers.my-router]
|
||||||
rule = "Path(`/test`)"
|
rule = "Path(`/test`)"
|
||||||
service = "whoami"
|
service = "whoami"
|
||||||
entrypoint=["tcp"]
|
entrypoints = ["tcp"]
|
||||||
|
|
||||||
[http.routers.my-https-router]
|
[http.routers.my-https-router]
|
||||||
entryPoints=["tcp"]
|
entryPoints=["tcp"]
|
||||||
|
@ -41,14 +41,14 @@
|
||||||
service = "whoami-a"
|
service = "whoami-a"
|
||||||
entryPoints = [ "tcp" ]
|
entryPoints = [ "tcp" ]
|
||||||
[tcp.routers.to-whoami-a.tls]
|
[tcp.routers.to-whoami-a.tls]
|
||||||
passthrough=true
|
passthrough = true
|
||||||
|
|
||||||
[tcp.routers.to-whoami-b]
|
[tcp.routers.to-whoami-b]
|
||||||
rule = "HostSNI(`whoami-b.test`)"
|
rule = "HostSNI(`whoami-b.test`)"
|
||||||
service = "whoami-b"
|
service = "whoami-b"
|
||||||
entryPoints = [ "tcp" ]
|
entryPoints = [ "tcp" ]
|
||||||
[tcp.routers.to-whoami-b.tls]
|
[tcp.routers.to-whoami-b.tls]
|
||||||
passthrough=true
|
passthrough = true
|
||||||
|
|
||||||
[tcp.routers.to-whoami-no-cert]
|
[tcp.routers.to-whoami-no-cert]
|
||||||
rule = "HostSNI(`whoami-c.test`)"
|
rule = "HostSNI(`whoami-c.test`)"
|
||||||
|
|
|
@ -31,4 +31,3 @@
|
||||||
passHostHeader = true
|
passHostHeader = true
|
||||||
[[http.services.keepalive.loadBalancer.servers]]
|
[[http.services.keepalive.loadBalancer.servers]]
|
||||||
url = "{{ .KeepAliveServer }}"
|
url = "{{ .KeepAliveServer }}"
|
||||||
weight = 1
|
|
||||||
|
|
|
@ -58,13 +58,13 @@
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
||||||
[http.services.service2]
|
[http.services.service2]
|
||||||
passHostHeader = true
|
|
||||||
[http.services.service2.loadBalancer]
|
[http.services.service2.loadBalancer]
|
||||||
|
passHostHeader = true
|
||||||
[[http.services.service2.loadBalancer.servers]]
|
[[http.services.service2.loadBalancer.servers]]
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
||||||
[http.services.service3]
|
[http.services.service3]
|
||||||
passHostHeader = true
|
|
||||||
[http.services.service3.loadBalancer]
|
[http.services.service3.loadBalancer]
|
||||||
|
passHostHeader = true
|
||||||
[[http.services.service3.loadBalancer.servers]]
|
[[http.services.service3.loadBalancer.servers]]
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
|
@ -57,13 +57,13 @@
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
||||||
[http.services.service2]
|
[http.services.service2]
|
||||||
passHostHeader = true
|
|
||||||
[http.services.service2.loadBalancer]
|
[http.services.service2.loadBalancer]
|
||||||
|
passHostHeader = true
|
||||||
[[http.services.service2.loadBalancer.servers]]
|
[[http.services.service2.loadBalancer.servers]]
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
||||||
[http.services.service3]
|
[http.services.service3]
|
||||||
passHostHeader = true
|
|
||||||
[http.services.service3.loadBalancer]
|
[http.services.service3.loadBalancer]
|
||||||
|
passHostHeader = true
|
||||||
[[http.services.service3.loadBalancer.servers]]
|
[[http.services.service3.loadBalancer.servers]]
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
|
@ -53,13 +53,13 @@
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
||||||
[http.services.service2]
|
[http.services.service2]
|
||||||
passHostHeader = true
|
|
||||||
[http.services.service2.loadBalancer]
|
[http.services.service2.loadBalancer]
|
||||||
|
passHostHeader = true
|
||||||
[[http.services.service2.loadBalancer.servers]]
|
[[http.services.service2.loadBalancer.servers]]
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
||||||
[http.services.service3]
|
[http.services.service3]
|
||||||
passHostHeader = true
|
|
||||||
[http.services.service3.loadBalancer]
|
[http.services.service3.loadBalancer]
|
||||||
|
passHostHeader = true
|
||||||
[[http.services.service3.loadBalancer.servers]]
|
[[http.services.service3.loadBalancer.servers]]
|
||||||
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
url = "http://{{.WhoAmiIP}}:{{.WhoAmiPort}}"
|
||||||
|
|
|
@ -4,7 +4,7 @@ type Yo struct {
|
||||||
Foo string `description:"Foo description"`
|
Foo string `description:"Foo description"`
|
||||||
Fii string `description:"Fii description"`
|
Fii string `description:"Fii description"`
|
||||||
Fuu string `description:"Fuu description"`
|
Fuu string `description:"Fuu description"`
|
||||||
Yi *Yi `label:"allowEmpty"`
|
Yi *Yi `label:"allowEmpty" file:"allowEmpty"`
|
||||||
Yu *Yi
|
Yu *Yi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ type HTTPConfiguration struct {
|
||||||
// Model is a set of default router's values.
|
// Model is a set of default router's values.
|
||||||
type Model struct {
|
type Model struct {
|
||||||
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||||
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty"`
|
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
@ -42,7 +42,7 @@ type Router struct {
|
||||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
||||||
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
|
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,omitempty"`
|
||||||
Priority int `json:"priority,omitempty" toml:"priority,omitempty,omitzero" yaml:"priority,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"`
|
TLS *RouterTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
@ -103,7 +103,7 @@ func (w *WRRService) SetDefaults() {
|
||||||
|
|
||||||
// Sticky holds the sticky configuration.
|
// Sticky holds the sticky configuration.
|
||||||
type Sticky struct {
|
type Sticky struct {
|
||||||
Cookie *Cookie `json:"cookie,omitempty" toml:"cookie,omitempty" yaml:"cookie,omitempty" label:"allowEmpty"`
|
Cookie *Cookie `json:"cookie,omitempty" toml:"cookie,omitempty" yaml:"cookie,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
@ -120,7 +120,7 @@ type Cookie struct {
|
||||||
|
|
||||||
// ServersLoadBalancer holds the ServersLoadBalancer configuration.
|
// ServersLoadBalancer holds the ServersLoadBalancer configuration.
|
||||||
type ServersLoadBalancer struct {
|
type ServersLoadBalancer struct {
|
||||||
Sticky *Sticky `json:"sticky,omitempty" toml:"sticky,omitempty" yaml:"sticky,omitempty" label:"allowEmpty"`
|
Sticky *Sticky `json:"sticky,omitempty" toml:"sticky,omitempty" yaml:"sticky,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Servers []Server `json:"servers,omitempty" toml:"servers,omitempty" yaml:"servers,omitempty" label-slice-as-struct:"server"`
|
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"`
|
HealthCheck *HealthCheck `json:"healthCheck,omitempty" toml:"healthCheck,omitempty" yaml:"healthCheck,omitempty"`
|
||||||
PassHostHeader *bool `json:"passHostHeader" toml:"passHostHeader" yaml:"passHostHeader"`
|
PassHostHeader *bool `json:"passHostHeader" toml:"passHostHeader" yaml:"passHostHeader"`
|
||||||
|
@ -162,8 +162,8 @@ type ResponseForwarding struct {
|
||||||
// Server holds the server configuration.
|
// Server holds the server configuration.
|
||||||
type Server struct {
|
type Server struct {
|
||||||
URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"`
|
URL string `json:"url,omitempty" toml:"url,omitempty" yaml:"url,omitempty" label:"-"`
|
||||||
Scheme string `toml:"-" json:"-" yaml:"-"`
|
Scheme string `toml:"-" json:"-" yaml:"-" file:"-"`
|
||||||
Port string `toml:"-" json:"-" yaml:"-"`
|
Port string `toml:"-" json:"-" yaml:"-" file:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults Default values for a Server.
|
// SetDefaults Default values for a Server.
|
||||||
|
|
|
@ -34,7 +34,7 @@ type Middleware struct {
|
||||||
InFlightReq *InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"`
|
InFlightReq *InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"`
|
||||||
Buffering *Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"`
|
Buffering *Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"`
|
||||||
CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,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"`
|
Compress *Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
PassTLSClientCert *PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"`
|
PassTLSClientCert *PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"`
|
||||||
Retry *Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"`
|
Retry *Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"`
|
||||||
ContentType *ContentType `json:"contentType,omitempty" toml:"contentType,omitempty" yaml:"contentType,omitempty"`
|
ContentType *ContentType `json:"contentType,omitempty" toml:"contentType,omitempty" yaml:"contentType,omitempty"`
|
||||||
|
@ -275,7 +275,7 @@ func (s *IPStrategy) Get() (ip.Strategy, error) {
|
||||||
// IPWhiteList holds the ip white list configuration.
|
// IPWhiteList holds the ip white list configuration.
|
||||||
type IPWhiteList struct {
|
type IPWhiteList struct {
|
||||||
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
||||||
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty"`
|
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -50,7 +50,7 @@ type TCPRouter struct {
|
||||||
EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty"`
|
EntryPoints []string `json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty"`
|
||||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty"`
|
||||||
Rule string `json:"rule,omitempty" toml:"rule,omitempty" yaml:"rule,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"`
|
TLS *RouterTCPTLSConfig `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
|
|
|
@ -78,5 +78,5 @@ func (l *UDPServersLoadBalancer) Mergeable(loadBalancer *UDPServersLoadBalancer)
|
||||||
// UDPServer defines a UDP server configuration.
|
// UDPServer defines a UDP server configuration.
|
||||||
type UDPServer struct {
|
type UDPServer struct {
|
||||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
|
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty" label:"-"`
|
||||||
Port string `toml:"-" json:"-" yaml:"-"`
|
Port string `toml:"-" json:"-" yaml:"-" file:"-"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/containous/traefik/v2/pkg/config/parser"
|
"github.com/containous/traefik/v2/pkg/config/parser"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Decode decodes the given configuration file into the given element.
|
// Decode decodes the given configuration file into the given element.
|
||||||
|
@ -22,11 +26,57 @@ func Decode(filePath string, element interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
metaOpts := parser.MetadataOpts{TagName: parser.TagLabel, AllowSliceAsStruct: true}
|
metaOpts := parser.MetadataOpts{TagName: parser.TagFile, AllowSliceAsStruct: false}
|
||||||
err = parser.AddMetadata(element, root, metaOpts)
|
err = parser.AddMetadata(element, root, metaOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return parser.Fill(element, root, parser.FillerOpts{AllowSliceAsStruct: true})
|
return parser.Fill(element, root, parser.FillerOpts{AllowSliceAsStruct: false})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeContent decodes the given configuration file content into the given element.
|
||||||
|
// The operation goes through three stages roughly summarized as:
|
||||||
|
// file contents -> tree of untyped nodes
|
||||||
|
// untyped nodes -> nodes augmented with metadata such as kind (inferred from element)
|
||||||
|
// "typed" nodes -> typed element.
|
||||||
|
func DecodeContent(content string, extension string, element interface{}) error {
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
|
||||||
|
switch extension {
|
||||||
|
case ".toml":
|
||||||
|
_, err := toml.Decode(content, &data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case ".yml", ".yaml":
|
||||||
|
var err error
|
||||||
|
err = yaml.Unmarshal([]byte(content), &data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported file extension: %s", extension)
|
||||||
|
}
|
||||||
|
|
||||||
|
filters := getRootFieldNames(element)
|
||||||
|
|
||||||
|
node, err := decodeRawToNode(data, parser.DefaultRootName, filters...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(node.Children) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
metaOpts := parser.MetadataOpts{TagName: parser.TagFile, AllowSliceAsStruct: false}
|
||||||
|
err = parser.AddMetadata(element, node, metaOpts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser.Fill(element, node, parser.FillerOpts{AllowSliceAsStruct: false})
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,32 @@ fii = "bir"
|
||||||
assert.Equal(t, expected, element)
|
assert.Equal(t, expected, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecodeContent_TOML(t *testing.T) {
|
||||||
|
content := `
|
||||||
|
foo = "bar"
|
||||||
|
fii = "bir"
|
||||||
|
[yi]
|
||||||
|
`
|
||||||
|
|
||||||
|
element := &Yo{
|
||||||
|
Fuu: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := DecodeContent(content, ".toml", element)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expected := &Yo{
|
||||||
|
Foo: "bar",
|
||||||
|
Fii: "bir",
|
||||||
|
Fuu: "test",
|
||||||
|
Yi: &Yi{
|
||||||
|
Foo: "foo",
|
||||||
|
Fii: "fii",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, element)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDecode_YAML(t *testing.T) {
|
func TestDecode_YAML(t *testing.T) {
|
||||||
f, err := ioutil.TempFile("", "traefik-config-*.yaml")
|
f, err := ioutil.TempFile("", "traefik-config-*.yaml")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -74,3 +100,29 @@ yi: {}
|
||||||
}
|
}
|
||||||
assert.Equal(t, expected, element)
|
assert.Equal(t, expected, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDecodeContent_YAML(t *testing.T) {
|
||||||
|
content := `
|
||||||
|
foo: bar
|
||||||
|
fii: bir
|
||||||
|
yi: {}
|
||||||
|
`
|
||||||
|
|
||||||
|
element := &Yo{
|
||||||
|
Fuu: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := DecodeContent(content, ".yaml", element)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expected := &Yo{
|
||||||
|
Foo: "bar",
|
||||||
|
Fii: "bir",
|
||||||
|
Fuu: "test",
|
||||||
|
Yi: &Yi{
|
||||||
|
Foo: "foo",
|
||||||
|
Fii: "fii",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, element)
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ type Yo struct {
|
||||||
Foo string
|
Foo string
|
||||||
Fii string
|
Fii string
|
||||||
Fuu string
|
Fuu string
|
||||||
Yi *Yi `label:"allowEmpty"`
|
Yi *Yi `file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yo) SetDefaults() {
|
func (y *Yo) SetDefaults() {
|
||||||
|
|
|
@ -6,6 +6,11 @@ const (
|
||||||
// - "-": ignore the field.
|
// - "-": ignore the field.
|
||||||
TagLabel = "label"
|
TagLabel = "label"
|
||||||
|
|
||||||
|
// TagFile allows to apply a custom behavior.
|
||||||
|
// - "allowEmpty": allows to create an empty struct.
|
||||||
|
// - "-": ignore the field.
|
||||||
|
TagFile = "file"
|
||||||
|
|
||||||
// TagLabelSliceAsStruct allows to use a slice of struct by creating one entry into the slice.
|
// TagLabelSliceAsStruct allows to use a slice of struct by creating one entry into the slice.
|
||||||
// The value is the substitution name used in the label to access the slice.
|
// The value is the substitution name used in the label to access the slice.
|
||||||
TagLabelSliceAsStruct = "label-slice-as-struct"
|
TagLabelSliceAsStruct = "label-slice-as-struct"
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
type EntryPoint struct {
|
type EntryPoint struct {
|
||||||
Address string `description:"Entry point address." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
Address string `description:"Entry point address." json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
||||||
Transport *EntryPointsTransport `description:"Configures communication between clients and Traefik." json:"transport,omitempty" toml:"transport,omitempty" yaml:"transport,omitempty"`
|
Transport *EntryPointsTransport `description:"Configures communication between clients and Traefik." json:"transport,omitempty" toml:"transport,omitempty" yaml:"transport,omitempty"`
|
||||||
ProxyProtocol *ProxyProtocol `description:"Proxy-Protocol configuration." json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty"`
|
ProxyProtocol *ProxyProtocol `description:"Proxy-Protocol configuration." json:"proxyProtocol,omitempty" toml:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
ForwardedHeaders *ForwardedHeaders `description:"Trust client forwarding headers." json:"forwardedHeaders,omitempty" toml:"forwardedHeaders,omitempty" yaml:"forwardedHeaders,omitempty"`
|
ForwardedHeaders *ForwardedHeaders `description:"Trust client forwarding headers." json:"forwardedHeaders,omitempty" toml:"forwardedHeaders,omitempty" yaml:"forwardedHeaders,omitempty"`
|
||||||
HTTP HTTPConfig `description:"HTTP configuration." json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty"`
|
HTTP HTTPConfig `description:"HTTP configuration." json:"http,omitempty" toml:"http,omitempty" yaml:"http,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ func (ep *EntryPoint) SetDefaults() {
|
||||||
type HTTPConfig struct {
|
type HTTPConfig struct {
|
||||||
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty"`
|
Redirections *Redirections `description:"Set of redirection" json:"redirections,omitempty" toml:"redirections,omitempty" yaml:"redirections,omitempty"`
|
||||||
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
Middlewares []string `description:"Default middlewares for the routers linked to the entry point." json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty"`
|
||||||
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty"`
|
TLS *TLSConfig `description:"Default TLS configuration for the routers linked to the entry point." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirections is a set of redirection for an entry point.
|
// Redirections is a set of redirection for an entry point.
|
||||||
|
|
|
@ -57,15 +57,15 @@ type Configuration struct {
|
||||||
EntryPoints EntryPoints `description:"Entry points definition." json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"`
|
EntryPoints EntryPoints `description:"Entry points definition." json:"entryPoints,omitempty" toml:"entryPoints,omitempty" yaml:"entryPoints,omitempty" export:"true"`
|
||||||
Providers *Providers `description:"Providers configuration." json:"providers,omitempty" toml:"providers,omitempty" yaml:"providers,omitempty" export:"true"`
|
Providers *Providers `description:"Providers configuration." json:"providers,omitempty" toml:"providers,omitempty" yaml:"providers,omitempty" export:"true"`
|
||||||
|
|
||||||
API *API `description:"Enable api/dashboard." json:"api,omitempty" toml:"api,omitempty" yaml:"api,omitempty" label:"allowEmpty" export:"true"`
|
API *API `description:"Enable api/dashboard." json:"api,omitempty" toml:"api,omitempty" yaml:"api,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
Metrics *types.Metrics `description:"Enable a metrics exporter." json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"`
|
Metrics *types.Metrics `description:"Enable a metrics exporter." json:"metrics,omitempty" toml:"metrics,omitempty" yaml:"metrics,omitempty" export:"true"`
|
||||||
Ping *ping.Handler `description:"Enable ping." json:"ping,omitempty" toml:"ping,omitempty" yaml:"ping,omitempty" label:"allowEmpty" export:"true"`
|
Ping *ping.Handler `description:"Enable ping." json:"ping,omitempty" toml:"ping,omitempty" yaml:"ping,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
|
|
||||||
Log *types.TraefikLog `description:"Traefik log settings." json:"log,omitempty" toml:"log,omitempty" yaml:"log,omitempty" label:"allowEmpty" export:"true"`
|
Log *types.TraefikLog `description:"Traefik log settings." json:"log,omitempty" toml:"log,omitempty" yaml:"log,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
AccessLog *types.AccessLog `description:"Access log settings." json:"accessLog,omitempty" toml:"accessLog,omitempty" yaml:"accessLog,omitempty" label:"allowEmpty" export:"true"`
|
AccessLog *types.AccessLog `description:"Access log settings." json:"accessLog,omitempty" toml:"accessLog,omitempty" yaml:"accessLog,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
Tracing *Tracing `description:"OpenTracing configuration." json:"tracing,omitempty" toml:"tracing,omitempty" yaml:"tracing,omitempty" label:"allowEmpty" export:"true"`
|
Tracing *Tracing `description:"OpenTracing configuration." json:"tracing,omitempty" toml:"tracing,omitempty" yaml:"tracing,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
|
|
||||||
HostResolver *types.HostResolverConfig `description:"Enable CNAME Flattening." json:"hostResolver,omitempty" toml:"hostResolver,omitempty" yaml:"hostResolver,omitempty" label:"allowEmpty" export:"true"`
|
HostResolver *types.HostResolverConfig `description:"Enable CNAME Flattening." json:"hostResolver,omitempty" toml:"hostResolver,omitempty" yaml:"hostResolver,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
|
|
||||||
CertificatesResolvers map[string]CertificateResolver `description:"Certificates resolvers configuration." json:"certificatesResolvers,omitempty" toml:"certificatesResolvers,omitempty" yaml:"certificatesResolvers,omitempty" export:"true"`
|
CertificatesResolvers map[string]CertificateResolver `description:"Certificates resolvers configuration." json:"certificatesResolvers,omitempty" toml:"certificatesResolvers,omitempty" yaml:"certificatesResolvers,omitempty" export:"true"`
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,8 @@ type CertificateResolver struct {
|
||||||
|
|
||||||
// Global holds the global configuration.
|
// Global holds the global configuration.
|
||||||
type Global struct {
|
type Global struct {
|
||||||
CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" export:"true"`
|
CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" export:"true"`
|
SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be enabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServersTransport options to configure communication between Traefik and the servers.
|
// ServersTransport options to configure communication between Traefik and the servers.
|
||||||
|
@ -95,8 +95,8 @@ type API struct {
|
||||||
Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"`
|
Dashboard bool `description:"Activate dashboard." json:"dashboard,omitempty" toml:"dashboard,omitempty" yaml:"dashboard,omitempty" export:"true"`
|
||||||
Debug bool `description:"Enable additional endpoints for debugging and profiling." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"`
|
Debug bool `description:"Enable additional endpoints for debugging and profiling." json:"debug,omitempty" toml:"debug,omitempty" yaml:"debug,omitempty" export:"true"`
|
||||||
// TODO: Re-enable statistics
|
// TODO: Re-enable statistics
|
||||||
// Statistics *types.Statistics `description:"Enable more detailed statistics." json:"statistics,omitempty" toml:"statistics,omitempty" yaml:"statistics,omitempty" export:"true" label:"allowEmpty"`
|
// Statistics *types.Statistics `description:"Enable more detailed statistics." json:"statistics,omitempty" toml:"statistics,omitempty" yaml:"statistics,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
DashboardAssets *assetfs.AssetFS `json:"-" toml:"-" yaml:"-" label:"-"`
|
DashboardAssets *assetfs.AssetFS `json:"-" toml:"-" yaml:"-" label:"-" file:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
|
@ -144,12 +144,12 @@ func (a *LifeCycle) SetDefaults() {
|
||||||
type Tracing struct {
|
type Tracing struct {
|
||||||
ServiceName string `description:"Set the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
|
ServiceName string `description:"Set the name for this service." json:"serviceName,omitempty" toml:"serviceName,omitempty" yaml:"serviceName,omitempty" export:"true"`
|
||||||
SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"`
|
SpanNameLimit int `description:"Set the maximum character limit for Span names (default 0 = no limit)." json:"spanNameLimit,omitempty" toml:"spanNameLimit,omitempty" yaml:"spanNameLimit,omitempty" export:"true"`
|
||||||
Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" export:"true" label:"allowEmpty"`
|
Jaeger *jaeger.Config `description:"Settings for Jaeger." json:"jaeger,omitempty" toml:"jaeger,omitempty" yaml:"jaeger,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" export:"true" label:"allowEmpty"`
|
Zipkin *zipkin.Config `description:"Settings for Zipkin." json:"zipkin,omitempty" toml:"zipkin,omitempty" yaml:"zipkin,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty"`
|
Datadog *datadog.Config `description:"Settings for Datadog." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" export:"true" label:"allowEmpty"`
|
Instana *instana.Config `description:"Settings for Instana." json:"instana,omitempty" toml:"instana,omitempty" yaml:"instana,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" export:"true" label:"allowEmpty"`
|
Haystack *haystack.Config `description:"Settings for Haystack." json:"haystack,omitempty" toml:"haystack,omitempty" yaml:"haystack,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Elastic *elastic.Config `description:"Settings for Elastic." json:"elastic,omitempty" toml:"elastic,omitempty" yaml:"elastic,omitempty" export:"true" label:"allowEmpty"`
|
Elastic *elastic.Config `description:"Settings for Elastic." json:"elastic,omitempty" toml:"elastic,omitempty" yaml:"elastic,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
|
@ -162,19 +162,19 @@ func (t *Tracing) SetDefaults() {
|
||||||
type Providers struct {
|
type Providers struct {
|
||||||
ProvidersThrottleDuration types.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." json:"providersThrottleDuration,omitempty" toml:"providersThrottleDuration,omitempty" yaml:"providersThrottleDuration,omitempty" export:"true"`
|
ProvidersThrottleDuration types.Duration `description:"Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time." json:"providersThrottleDuration,omitempty" toml:"providersThrottleDuration,omitempty" yaml:"providersThrottleDuration,omitempty" export:"true"`
|
||||||
|
|
||||||
Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty"`
|
Docker *docker.Provider `description:"Enable Docker backend with default settings." json:"docker,omitempty" toml:"docker,omitempty" yaml:"docker,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"`
|
File *file.Provider `description:"Enable File backend with default settings." json:"file,omitempty" toml:"file,omitempty" yaml:"file,omitempty" export:"true"`
|
||||||
Marathon *marathon.Provider `description:"Enable Marathon backend with default settings." json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" export:"true" label:"allowEmpty"`
|
Marathon *marathon.Provider `description:"Enable Marathon backend with default settings." json:"marathon,omitempty" toml:"marathon,omitempty" yaml:"marathon,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty"`
|
KubernetesIngress *ingress.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesIngress,omitempty" toml:"kubernetesIngress,omitempty" yaml:"kubernetesIngress,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty"`
|
KubernetesCRD *crd.Provider `description:"Enable Kubernetes backend with default settings." json:"kubernetesCRD,omitempty" toml:"kubernetesCRD,omitempty" yaml:"kubernetesCRD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Rest *rest.Provider `description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" export:"true" label:"allowEmpty"`
|
Rest *rest.Provider `description:"Enable Rest backend with default settings." json:"rest,omitempty" toml:"rest,omitempty" yaml:"rest,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Rancher *rancher.Provider `description:"Enable Rancher backend with default settings." json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" export:"true" label:"allowEmpty"`
|
Rancher *rancher.Provider `description:"Enable Rancher backend with default settings." json:"rancher,omitempty" toml:"rancher,omitempty" yaml:"rancher,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
ConsulCatalog *consulcatalog.Provider `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty"`
|
ConsulCatalog *consulcatalog.Provider `description:"Enable ConsulCatalog backend with default settings." json:"consulCatalog,omitempty" toml:"consulCatalog,omitempty" yaml:"consulCatalog,omitempty"`
|
||||||
|
|
||||||
Consul *consul.Provider `description:"Enable Consul backend with default settings." json:"consul,omitempty" toml:"consul,omitempty" yaml:"consul,omitempty" export:"true" label:"allowEmpty"`
|
Consul *consul.Provider `description:"Enable Consul backend with default settings." json:"consul,omitempty" toml:"consul,omitempty" yaml:"consul,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Etcd *etcd.Provider `description:"Enable Etcd backend with default settings." json:"etcd,omitempty" toml:"etcd,omitempty" yaml:"etcd,omitempty" export:"true" label:"allowEmpty"`
|
Etcd *etcd.Provider `description:"Enable Etcd backend with default settings." json:"etcd,omitempty" toml:"etcd,omitempty" yaml:"etcd,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
ZooKeeper *zk.Provider `description:"Enable ZooKeeper backend with default settings." json:"zooKeeper,omitempty" toml:"zooKeeper,omitempty" yaml:"zooKeeper,omitempty" export:"true" label:"allowEmpty"`
|
ZooKeeper *zk.Provider `description:"Enable ZooKeeper backend with default settings." json:"zooKeeper,omitempty" toml:"zooKeeper,omitempty" yaml:"zooKeeper,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Redis *redis.Provider `description:"Enable Redis backend with default settings." json:"redis,omitempty" toml:"redis,omitempty" yaml:"redis,omitempty" export:"true" label:"allowEmpty"`
|
Redis *redis.Provider `description:"Enable Redis backend with default settings." json:"redis,omitempty" toml:"redis,omitempty" yaml:"redis,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEffectiveConfiguration adds missing configuration parameters derived from existing ones.
|
// SetEffectiveConfiguration adds missing configuration parameters derived from existing ones.
|
||||||
|
|
|
@ -38,9 +38,9 @@ type Configuration struct {
|
||||||
CAServer string `description:"CA server to use." json:"caServer,omitempty" toml:"caServer,omitempty" yaml:"caServer,omitempty"`
|
CAServer string `description:"CA server to use." json:"caServer,omitempty" toml:"caServer,omitempty" yaml:"caServer,omitempty"`
|
||||||
Storage string `description:"Storage to use." json:"storage,omitempty" toml:"storage,omitempty" yaml:"storage,omitempty"`
|
Storage string `description:"Storage to use." json:"storage,omitempty" toml:"storage,omitempty" yaml:"storage,omitempty"`
|
||||||
KeyType string `description:"KeyType used for generating certificate private key. Allow value 'EC256', 'EC384', 'RSA2048', 'RSA4096', 'RSA8192'." json:"keyType,omitempty" toml:"keyType,omitempty" yaml:"keyType,omitempty"`
|
KeyType string `description:"KeyType used for generating certificate private key. Allow value 'EC256', 'EC384', 'RSA2048', 'RSA4096', 'RSA8192'." json:"keyType,omitempty" toml:"keyType,omitempty" yaml:"keyType,omitempty"`
|
||||||
DNSChallenge *DNSChallenge `description:"Activate DNS-01 Challenge." json:"dnsChallenge,omitempty" toml:"dnsChallenge,omitempty" yaml:"dnsChallenge,omitempty" label:"allowEmpty"`
|
DNSChallenge *DNSChallenge `description:"Activate DNS-01 Challenge." json:"dnsChallenge,omitempty" toml:"dnsChallenge,omitempty" yaml:"dnsChallenge,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
HTTPChallenge *HTTPChallenge `description:"Activate HTTP-01 Challenge." json:"httpChallenge,omitempty" toml:"httpChallenge,omitempty" yaml:"httpChallenge,omitempty" label:"allowEmpty"`
|
HTTPChallenge *HTTPChallenge `description:"Activate HTTP-01 Challenge." json:"httpChallenge,omitempty" toml:"httpChallenge,omitempty" yaml:"httpChallenge,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
TLSChallenge *TLSChallenge `description:"Activate TLS-ALPN-01 Challenge." json:"tlsChallenge,omitempty" toml:"tlsChallenge,omitempty" yaml:"tlsChallenge,omitempty" label:"allowEmpty"`
|
TLSChallenge *TLSChallenge `description:"Activate TLS-ALPN-01 Challenge." json:"tlsChallenge,omitempty" toml:"tlsChallenge,omitempty" yaml:"tlsChallenge,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDefaults sets the default values.
|
// SetDefaults sets the default values.
|
||||||
|
|
|
@ -11,15 +11,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/Masterminds/sprig"
|
"github.com/Masterminds/sprig"
|
||||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||||
|
"github.com/containous/traefik/v2/pkg/config/file"
|
||||||
"github.com/containous/traefik/v2/pkg/log"
|
"github.com/containous/traefik/v2/pkg/log"
|
||||||
"github.com/containous/traefik/v2/pkg/provider"
|
"github.com/containous/traefik/v2/pkg/provider"
|
||||||
"github.com/containous/traefik/v2/pkg/safe"
|
"github.com/containous/traefik/v2/pkg/safe"
|
||||||
"github.com/containous/traefik/v2/pkg/tls"
|
"github.com/containous/traefik/v2/pkg/tls"
|
||||||
"gopkg.in/fsnotify.v1"
|
"gopkg.in/fsnotify.v1"
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const providerName = "file"
|
const providerName = "file"
|
||||||
|
@ -418,24 +417,11 @@ func (p *Provider) decodeConfiguration(filePath string, content string) (*dynami
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
switch strings.ToLower(filepath.Ext(filePath)) {
|
err := file.DecodeContent(content, strings.ToLower(filepath.Ext(filePath)), configuration)
|
||||||
case ".toml":
|
|
||||||
_, err := toml.Decode(content, configuration)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case ".yml", ".yaml":
|
|
||||||
var err error
|
|
||||||
err = yaml.Unmarshal([]byte(content), configuration)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported file extension: %s", filePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return configuration, nil
|
return configuration, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,11 +90,12 @@ func TestProvideWithoutWatch(t *testing.T) {
|
||||||
timeout := time.After(time.Second)
|
timeout := time.After(time.Second)
|
||||||
select {
|
select {
|
||||||
case conf := <-configChan:
|
case conf := <-configChan:
|
||||||
|
|
||||||
require.NotNil(t, conf.Configuration.HTTP)
|
require.NotNil(t, conf.Configuration.HTTP)
|
||||||
numServices := len(conf.Configuration.HTTP.Services) + len(conf.Configuration.TCP.Services) + len(conf.Configuration.UDP.Services)
|
numServices := len(conf.Configuration.HTTP.Services) + len(conf.Configuration.TCP.Services) + len(conf.Configuration.UDP.Services)
|
||||||
numRouters := len(conf.Configuration.HTTP.Routers) + len(conf.Configuration.TCP.Routers) + len(conf.Configuration.UDP.Routers)
|
numRouters := len(conf.Configuration.HTTP.Routers) + len(conf.Configuration.TCP.Routers) + len(conf.Configuration.UDP.Routers)
|
||||||
assert.Equal(t, numServices, test.expectedNumService)
|
assert.Equal(t, test.expectedNumService, numServices)
|
||||||
assert.Equal(t, numRouters, test.expectedNumRouter)
|
assert.Equal(t, test.expectedNumRouter, numRouters)
|
||||||
require.NotNil(t, conf.Configuration.TLS)
|
require.NotNil(t, conf.Configuration.TLS)
|
||||||
assert.Len(t, conf.Configuration.TLS.Certificates, test.expectedNumTLSConf)
|
assert.Len(t, conf.Configuration.TLS.Certificates, test.expectedNumTLSConf)
|
||||||
assert.Len(t, conf.Configuration.TLS.Options, test.expectedNumTLSOptions)
|
assert.Len(t, conf.Configuration.TLS.Options, test.expectedNumTLSOptions)
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
[tcp.services.applicationtcp-1.loadBalancer]
|
[tcp.services.applicationtcp-1.loadBalancer]
|
||||||
[[tcp.services.applicationtcp-1.loadBalancer.servers]]
|
[[tcp.services.applicationtcp-1.loadBalancer.servers]]
|
||||||
url = "http://172.17.0.9:80"
|
address = "http://172.17.0.9:80"
|
||||||
|
|
||||||
[udp.routers]
|
[udp.routers]
|
||||||
|
|
||||||
|
@ -77,4 +77,4 @@
|
||||||
|
|
||||||
[udp.services.applicationudp-1.loadBalancer]
|
[udp.services.applicationudp-1.loadBalancer]
|
||||||
[[udp.services.applicationudp-1.loadBalancer.servers]]
|
[[udp.services.applicationudp-1.loadBalancer.servers]]
|
||||||
url = "http://172.17.0.10:80"
|
address = "http://172.17.0.10:80"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[http.services]
|
[http.services]
|
||||||
{{ range $i, $e := until 20 }}
|
{{ range $i, $e := until 20 }}
|
||||||
[http.services.application-{{ $e }}]
|
[http.services.application-{{ $e }}.loadBalancer]
|
||||||
[[http.services.application-{{ $e }}.servers]]
|
[[http.services.application-{{ $e }}.loadBalancer.servers]]
|
||||||
url="http://127.0.0.1"
|
url = "http://127.0.0.1"
|
||||||
{{ end }}
|
{{ end }}
|
|
@ -1,6 +1,6 @@
|
||||||
http:
|
http:
|
||||||
{{ range $i, $e := until 20 }}
|
|
||||||
routers:
|
routers:
|
||||||
|
{{ range $i, $e := until 20 }}
|
||||||
router{{ $e }}:
|
router{{ $e }}:
|
||||||
service: application-1
|
service: application-1
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
@ -6,10 +6,10 @@ import (
|
||||||
|
|
||||||
// Metrics provides options to expose and send Traefik metrics to different third party monitoring systems.
|
// Metrics provides options to expose and send Traefik metrics to different third party monitoring systems.
|
||||||
type Metrics struct {
|
type Metrics struct {
|
||||||
Prometheus *Prometheus `description:"Prometheus metrics exporter type." json:"prometheus,omitempty" toml:"prometheus,omitempty" yaml:"prometheus,omitempty" export:"true" label:"allowEmpty"`
|
Prometheus *Prometheus `description:"Prometheus metrics exporter type." json:"prometheus,omitempty" toml:"prometheus,omitempty" yaml:"prometheus,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
Datadog *Datadog `description:"Datadog metrics exporter type." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty"`
|
Datadog *Datadog `description:"Datadog metrics exporter type." json:"datadog,omitempty" toml:"datadog,omitempty" yaml:"datadog,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
StatsD *Statsd `description:"StatsD metrics exporter type." json:"statsD,omitempty" toml:"statsD,omitempty" yaml:"statsD,omitempty" export:"true" label:"allowEmpty"`
|
StatsD *Statsd `description:"StatsD metrics exporter type." json:"statsD,omitempty" toml:"statsD,omitempty" yaml:"statsD,omitempty" export:"true" label:"allowEmpty" file:"allowEmpty"`
|
||||||
InfluxDB *InfluxDB `description:"InfluxDB metrics exporter type." json:"influxDB,omitempty" toml:"influxDB,omitempty" yaml:"influxDB,omitempty" label:"allowEmpty"`
|
InfluxDB *InfluxDB `description:"InfluxDB metrics exporter type." json:"influxDB,omitempty" toml:"influxDB,omitempty" yaml:"influxDB,omitempty" label:"allowEmpty" file:"allowEmpty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prometheus can contain specific configuration used by the Prometheus Metrics exporter.
|
// Prometheus can contain specific configuration used by the Prometheus Metrics exporter.
|
||||||
|
|
Loading…
Reference in a new issue