Add internal provider
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
This commit is contained in:
parent
2ee2e29262
commit
424e2a9439
71 changed files with 2523 additions and 1469 deletions
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"api": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 9223372036854775806
|
||||
},
|
||||
"dashboard": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"middlewares": [
|
||||
"dashboard_redirect@internal",
|
||||
"dashboard_stripprefix@internal"
|
||||
],
|
||||
"service": "dashboard@internal",
|
||||
"rule": "PathPrefix(`/`)",
|
||||
"priority": 9223372036854775805
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"dashboard_redirect": {
|
||||
"redirectRegex": {
|
||||
"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
|
||||
"replacement": "${1}/dashboard/",
|
||||
"permanent": true
|
||||
}
|
||||
},
|
||||
"dashboard_stripprefix": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"/dashboard/",
|
||||
"/dashboard"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"api": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 9223372036854775806
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"api": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
10
pkg/provider/traefik/fixtures/api_secure_with_dashboard.json
Normal file
10
pkg/provider/traefik/fixtures/api_secure_with_dashboard.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"api": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
76
pkg/provider/traefik/fixtures/full_configuration.json
Normal file
76
pkg/provider/traefik/fixtures/full_configuration.json
Normal file
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"api": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "api@internal",
|
||||
"rule": "PathPrefix(`/api`)",
|
||||
"priority": 9223372036854775806
|
||||
},
|
||||
"dashboard": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"middlewares": [
|
||||
"dashboard_redirect@internal",
|
||||
"dashboard_stripprefix@internal"
|
||||
],
|
||||
"service": "dashboard@internal",
|
||||
"rule": "PathPrefix(`/`)",
|
||||
"priority": 9223372036854775805
|
||||
},
|
||||
"ping": {
|
||||
"entryPoints": [
|
||||
"test"
|
||||
],
|
||||
"service": "ping@internal",
|
||||
"rule": "PathPrefix(`/ping`)",
|
||||
"priority": 9223372036854775807
|
||||
},
|
||||
"prometheus": {
|
||||
"entryPoints": [
|
||||
"test"
|
||||
],
|
||||
"service": "prometheus@internal",
|
||||
"rule": "PathPrefix(`/metrics`)",
|
||||
"priority": 9223372036854775807
|
||||
},
|
||||
"rest": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "rest@internal",
|
||||
"rule": "PathPrefix(`/api/providers`)",
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"middlewares": {
|
||||
"dashboard_redirect": {
|
||||
"redirectRegex": {
|
||||
"regex": "^(http:\\/\\/[^:]+(:\\d+)?)/$",
|
||||
"replacement": "${1}/dashboard/",
|
||||
"permanent": true
|
||||
}
|
||||
},
|
||||
"dashboard_stripprefix": {
|
||||
"stripPrefix": {
|
||||
"prefixes": [
|
||||
"/dashboard/",
|
||||
"/dashboard"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {},
|
||||
"ping": {},
|
||||
"prometheus": {},
|
||||
"rest": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
13
pkg/provider/traefik/fixtures/full_configuration_secure.json
Normal file
13
pkg/provider/traefik/fixtures/full_configuration_secure.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"api": {},
|
||||
"dashboard": {},
|
||||
"ping": {},
|
||||
"prometheus": {},
|
||||
"rest": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
9
pkg/provider/traefik/fixtures/ping_custom.json
Normal file
9
pkg/provider/traefik/fixtures/ping_custom.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"ping": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
19
pkg/provider/traefik/fixtures/ping_simple.json
Normal file
19
pkg/provider/traefik/fixtures/ping_simple.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"ping": {
|
||||
"entryPoints": [
|
||||
"test"
|
||||
],
|
||||
"service": "ping@internal",
|
||||
"rule": "PathPrefix(`/ping`)",
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"ping": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
9
pkg/provider/traefik/fixtures/prometheus_custom.json
Normal file
9
pkg/provider/traefik/fixtures/prometheus_custom.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"prometheus": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
19
pkg/provider/traefik/fixtures/prometheus_simple.json
Normal file
19
pkg/provider/traefik/fixtures/prometheus_simple.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"prometheus": {
|
||||
"entryPoints": [
|
||||
"test"
|
||||
],
|
||||
"service": "prometheus@internal",
|
||||
"rule": "PathPrefix(`/metrics`)",
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"prometheus": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
19
pkg/provider/traefik/fixtures/rest_insecure.json
Normal file
19
pkg/provider/traefik/fixtures/rest_insecure.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"http": {
|
||||
"routers": {
|
||||
"rest": {
|
||||
"entryPoints": [
|
||||
"traefik"
|
||||
],
|
||||
"service": "rest@internal",
|
||||
"rule": "PathPrefix(`/api/providers`)",
|
||||
"priority": 9223372036854775807
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"rest": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
9
pkg/provider/traefik/fixtures/rest_secure.json
Normal file
9
pkg/provider/traefik/fixtures/rest_secure.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"http": {
|
||||
"services": {
|
||||
"rest": {}
|
||||
}
|
||||
},
|
||||
"tcp": {},
|
||||
"tls": {}
|
||||
}
|
156
pkg/provider/traefik/internal.go
Normal file
156
pkg/provider/traefik/internal.go
Normal file
|
@ -0,0 +1,156 @@
|
|||
package traefik
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/containous/traefik/v2/pkg/config/static"
|
||||
"github.com/containous/traefik/v2/pkg/provider"
|
||||
"github.com/containous/traefik/v2/pkg/safe"
|
||||
"github.com/containous/traefik/v2/pkg/tls"
|
||||
)
|
||||
|
||||
var _ provider.Provider = (*Provider)(nil)
|
||||
|
||||
// Provider is a provider.Provider implementation that provides the internal routers.
|
||||
type Provider struct {
|
||||
staticCfg static.Configuration
|
||||
}
|
||||
|
||||
// New creates a new instance of the internal provider.
|
||||
func New(staticCfg static.Configuration) *Provider {
|
||||
return &Provider{staticCfg: staticCfg}
|
||||
}
|
||||
|
||||
// Provide allows the provider to provide configurations to traefik using the given configuration channel.
|
||||
func (i *Provider) Provide(configurationChan chan<- dynamic.Message, _ *safe.Pool) error {
|
||||
configurationChan <- dynamic.Message{
|
||||
ProviderName: "internal",
|
||||
Configuration: i.createConfiguration(),
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Init the provider.
|
||||
func (i *Provider) Init() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Provider) createConfiguration() *dynamic.Configuration {
|
||||
cfg := &dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: make(map[string]*dynamic.Router),
|
||||
Middlewares: make(map[string]*dynamic.Middleware),
|
||||
Services: make(map[string]*dynamic.Service),
|
||||
},
|
||||
TCP: &dynamic.TCPConfiguration{
|
||||
Routers: make(map[string]*dynamic.TCPRouter),
|
||||
Services: make(map[string]*dynamic.TCPService),
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{
|
||||
Stores: make(map[string]tls.Store),
|
||||
Options: make(map[string]tls.Options),
|
||||
},
|
||||
}
|
||||
|
||||
i.apiConfiguration(cfg)
|
||||
i.pingConfiguration(cfg)
|
||||
i.restConfiguration(cfg)
|
||||
i.prometheusConfiguration(cfg)
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (i *Provider) apiConfiguration(cfg *dynamic.Configuration) {
|
||||
if i.staticCfg.API == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if i.staticCfg.API.Insecure {
|
||||
cfg.HTTP.Routers["api"] = &dynamic.Router{
|
||||
EntryPoints: []string{"traefik"},
|
||||
Service: "api@internal",
|
||||
Priority: math.MaxInt64 - 1,
|
||||
Rule: "PathPrefix(`/api`)",
|
||||
}
|
||||
|
||||
if i.staticCfg.API.Dashboard {
|
||||
cfg.HTTP.Routers["dashboard"] = &dynamic.Router{
|
||||
EntryPoints: []string{"traefik"},
|
||||
Service: "dashboard@internal",
|
||||
Priority: math.MaxInt64 - 2,
|
||||
Rule: "PathPrefix(`/`)",
|
||||
Middlewares: []string{"dashboard_redirect@internal", "dashboard_stripprefix@internal"},
|
||||
}
|
||||
|
||||
cfg.HTTP.Middlewares["dashboard_redirect"] = &dynamic.Middleware{
|
||||
RedirectRegex: &dynamic.RedirectRegex{
|
||||
Regex: `^(http:\/\/[^:]+(:\d+)?)/$`,
|
||||
Replacement: "${1}/dashboard/",
|
||||
Permanent: true,
|
||||
},
|
||||
}
|
||||
cfg.HTTP.Middlewares["dashboard_stripprefix"] = &dynamic.Middleware{
|
||||
StripPrefix: &dynamic.StripPrefix{Prefixes: []string{"/dashboard/", "/dashboard"}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg.HTTP.Services["api"] = &dynamic.Service{}
|
||||
|
||||
if i.staticCfg.API.Dashboard {
|
||||
cfg.HTTP.Services["dashboard"] = &dynamic.Service{}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Provider) pingConfiguration(cfg *dynamic.Configuration) {
|
||||
if i.staticCfg.Ping == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !i.staticCfg.Ping.ManualRouting {
|
||||
cfg.HTTP.Routers["ping"] = &dynamic.Router{
|
||||
EntryPoints: []string{i.staticCfg.Ping.EntryPoint},
|
||||
Service: "ping@internal",
|
||||
Priority: math.MaxInt64,
|
||||
Rule: "PathPrefix(`/ping`)",
|
||||
}
|
||||
}
|
||||
|
||||
cfg.HTTP.Services["ping"] = &dynamic.Service{}
|
||||
}
|
||||
|
||||
func (i *Provider) restConfiguration(cfg *dynamic.Configuration) {
|
||||
if i.staticCfg.Providers == nil || i.staticCfg.Providers.Rest == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if i.staticCfg.Providers.Rest.Insecure {
|
||||
cfg.HTTP.Routers["rest"] = &dynamic.Router{
|
||||
EntryPoints: []string{"traefik"},
|
||||
Service: "rest@internal",
|
||||
Priority: math.MaxInt64,
|
||||
Rule: "PathPrefix(`/api/providers`)",
|
||||
}
|
||||
}
|
||||
|
||||
cfg.HTTP.Services["rest"] = &dynamic.Service{}
|
||||
}
|
||||
|
||||
func (i *Provider) prometheusConfiguration(cfg *dynamic.Configuration) {
|
||||
if i.staticCfg.Metrics == nil || i.staticCfg.Metrics.Prometheus == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !i.staticCfg.Metrics.Prometheus.ManualRouting {
|
||||
cfg.HTTP.Routers["prometheus"] = &dynamic.Router{
|
||||
EntryPoints: []string{i.staticCfg.Metrics.Prometheus.EntryPoint},
|
||||
Service: "prometheus@internal",
|
||||
Priority: math.MaxInt64,
|
||||
Rule: "PathPrefix(`/metrics`)",
|
||||
}
|
||||
}
|
||||
|
||||
cfg.HTTP.Services["prometheus"] = &dynamic.Service{}
|
||||
}
|
199
pkg/provider/traefik/internal_test.go
Normal file
199
pkg/provider/traefik/internal_test.go
Normal file
|
@ -0,0 +1,199 @@
|
|||
package traefik
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/containous/traefik/v2/pkg/config/static"
|
||||
"github.com/containous/traefik/v2/pkg/ping"
|
||||
"github.com/containous/traefik/v2/pkg/provider/rest"
|
||||
"github.com/containous/traefik/v2/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var updateExpected = flag.Bool("update_expected", false, "Update expected files in fixtures")
|
||||
|
||||
func Test_createConfiguration(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
staticCfg static.Configuration
|
||||
}{
|
||||
{
|
||||
desc: "full_configuration.json",
|
||||
staticCfg: static.Configuration{
|
||||
API: &static.API{
|
||||
Insecure: true,
|
||||
Dashboard: true,
|
||||
},
|
||||
Ping: &ping.Handler{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: false,
|
||||
},
|
||||
Providers: &static.Providers{
|
||||
Rest: &rest.Provider{
|
||||
Insecure: true,
|
||||
},
|
||||
},
|
||||
Metrics: &types.Metrics{
|
||||
Prometheus: &types.Prometheus{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "full_configuration_secure.json",
|
||||
staticCfg: static.Configuration{
|
||||
API: &static.API{
|
||||
Insecure: false,
|
||||
Dashboard: true,
|
||||
},
|
||||
Ping: &ping.Handler{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: true,
|
||||
},
|
||||
Providers: &static.Providers{
|
||||
Rest: &rest.Provider{
|
||||
Insecure: false,
|
||||
},
|
||||
},
|
||||
Metrics: &types.Metrics{
|
||||
Prometheus: &types.Prometheus{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "api_insecure_with_dashboard.json",
|
||||
staticCfg: static.Configuration{
|
||||
API: &static.API{
|
||||
Insecure: true,
|
||||
Dashboard: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "api_insecure_without_dashboard.json",
|
||||
staticCfg: static.Configuration{
|
||||
API: &static.API{
|
||||
Insecure: true,
|
||||
Dashboard: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "api_secure_with_dashboard.json",
|
||||
staticCfg: static.Configuration{
|
||||
API: &static.API{
|
||||
Insecure: false,
|
||||
Dashboard: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "api_secure_without_dashboard.json",
|
||||
staticCfg: static.Configuration{
|
||||
API: &static.API{
|
||||
Insecure: false,
|
||||
Dashboard: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "ping_simple.json",
|
||||
staticCfg: static.Configuration{
|
||||
Ping: &ping.Handler{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "ping_custom.json",
|
||||
staticCfg: static.Configuration{
|
||||
Ping: &ping.Handler{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "rest_insecure.json",
|
||||
staticCfg: static.Configuration{
|
||||
Providers: &static.Providers{
|
||||
Rest: &rest.Provider{
|
||||
Insecure: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "rest_secure.json",
|
||||
staticCfg: static.Configuration{
|
||||
Providers: &static.Providers{
|
||||
Rest: &rest.Provider{
|
||||
Insecure: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "prometheus_simple.json",
|
||||
staticCfg: static.Configuration{
|
||||
Metrics: &types.Metrics{
|
||||
Prometheus: &types.Prometheus{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "prometheus_custom.json",
|
||||
staticCfg: static.Configuration{
|
||||
Metrics: &types.Metrics{
|
||||
Prometheus: &types.Prometheus{
|
||||
EntryPoint: "test",
|
||||
ManualRouting: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
provider := Provider{staticCfg: test.staticCfg}
|
||||
|
||||
cfg := provider.createConfiguration()
|
||||
|
||||
filename := filepath.Join("fixtures", test.desc)
|
||||
|
||||
if *updateExpected {
|
||||
newJSON, err := json.MarshalIndent(cfg, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = ioutil.WriteFile(filename, newJSON, 0644)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
expectedJSON, err := ioutil.ReadFile(filename)
|
||||
require.NoError(t, err)
|
||||
|
||||
actualJSON, err := json.MarshalIndent(cfg, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, string(expectedJSON), string(actualJSON))
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue