1
0
Fork 0

Entry point redirection and default routers configuration

Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
Traefiker Bot 2020-03-05 12:46:05 +01:00 committed by GitHub
parent 93a7af270f
commit a6040c623b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 1016 additions and 126 deletions

View file

@ -7,12 +7,13 @@ import (
"github.com/containous/traefik/v2/pkg/tls"
)
func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configuration {
func mergeConfiguration(configurations dynamic.Configurations, entryPoints []string) dynamic.Configuration {
conf := dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: make(map[string]*dynamic.Router),
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: make(map[string]*dynamic.Model),
},
TCP: &dynamic.TCPConfiguration{
Routers: make(map[string]*dynamic.TCPRouter),
@ -33,6 +34,13 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
for pvd, configuration := range configurations {
if configuration.HTTP != nil {
for routerName, router := range configuration.HTTP.Routers {
if len(router.EntryPoints) == 0 {
log.WithoutContext().
WithField(log.RouterName, routerName).
Debugf("No entryPoint defined for this router, using the default one(s) instead: %+v", entryPoints)
router.EntryPoints = entryPoints
}
conf.HTTP.Routers[provider.MakeQualifiedName(pvd, routerName)] = router
}
for middlewareName, middleware := range configuration.HTTP.Middlewares {
@ -41,6 +49,9 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
for serviceName, service := range configuration.HTTP.Services {
conf.HTTP.Services[provider.MakeQualifiedName(pvd, serviceName)] = service
}
for modelName, model := range configuration.HTTP.Models {
conf.HTTP.Models[provider.MakeQualifiedName(pvd, modelName)] = model
}
}
if configuration.TCP != nil {
@ -101,3 +112,45 @@ func mergeConfiguration(configurations dynamic.Configurations) dynamic.Configura
return conf
}
func applyModel(cfg dynamic.Configuration) dynamic.Configuration {
if cfg.HTTP == nil || len(cfg.HTTP.Models) == 0 {
return cfg
}
rts := make(map[string]*dynamic.Router)
for name, router := range cfg.HTTP.Routers {
eps := router.EntryPoints
router.EntryPoints = nil
for _, epName := range eps {
m, ok := cfg.HTTP.Models[epName+"@internal"]
if ok {
cp := router.DeepCopy()
cp.EntryPoints = []string{epName}
if cp.TLS == nil {
cp.TLS = m.TLS
}
cp.Middlewares = append(m.Middlewares, cp.Middlewares...)
rtName := name
if len(eps) > 1 {
rtName = epName + "-" + name
}
rts[rtName] = cp
} else {
router.EntryPoints = append(router.EntryPoints, epName)
rts[name] = router
}
}
}
cfg.HTTP.Routers = rts
return cfg
}

View file

@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"
)
func TestAggregator(t *testing.T) {
func Test_mergeConfiguration(t *testing.T) {
testCases := []struct {
desc string
given dynamic.Configurations
@ -21,6 +21,7 @@ func TestAggregator(t *testing.T) {
Routers: make(map[string]*dynamic.Router),
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: make(map[string]*dynamic.Model),
},
},
{
@ -42,7 +43,9 @@ func TestAggregator(t *testing.T) {
},
expected: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"router-1@provider-1": {},
"router-1@provider-1": {
EntryPoints: []string{"defaultEP"},
},
},
Middlewares: map[string]*dynamic.Middleware{
"middleware-1@provider-1": {},
@ -50,6 +53,7 @@ func TestAggregator(t *testing.T) {
Services: map[string]*dynamic.Service{
"service-1@provider-1": {},
},
Models: make(map[string]*dynamic.Model),
},
},
{
@ -84,8 +88,12 @@ func TestAggregator(t *testing.T) {
},
expected: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"router-1@provider-1": {},
"router-1@provider-2": {},
"router-1@provider-1": {
EntryPoints: []string{"defaultEP"},
},
"router-1@provider-2": {
EntryPoints: []string{"defaultEP"},
},
},
Middlewares: map[string]*dynamic.Middleware{
"middleware-1@provider-1": {},
@ -95,6 +103,7 @@ func TestAggregator(t *testing.T) {
"service-1@provider-1": {},
"service-1@provider-2": {},
},
Models: make(map[string]*dynamic.Model),
},
},
}
@ -104,13 +113,13 @@ func TestAggregator(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual := mergeConfiguration(test.given)
actual := mergeConfiguration(test.given, []string{"defaultEP"})
assert.Equal(t, test.expected, actual.HTTP)
})
}
}
func TestAggregator_tlsoptions(t *testing.T) {
func Test_mergeConfiguration_tlsOptions(t *testing.T) {
testCases := []struct {
desc string
given dynamic.Configurations
@ -289,13 +298,13 @@ func TestAggregator_tlsoptions(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual := mergeConfiguration(test.given)
actual := mergeConfiguration(test.given, []string{"defaultEP"})
assert.Equal(t, test.expected, actual.TLS.Options)
})
}
}
func TestAggregator_tlsStore(t *testing.T) {
func Test_mergeConfiguration_tlsStore(t *testing.T) {
testCases := []struct {
desc string
given dynamic.Configurations
@ -381,8 +390,202 @@ func TestAggregator_tlsStore(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual := mergeConfiguration(test.given)
actual := mergeConfiguration(test.given, []string{"defaultEP"})
assert.Equal(t, test.expected, actual.TLS.Stores)
})
}
}
func Test_applyModel(t *testing.T) {
testCases := []struct {
desc string
input dynamic.Configuration
expected dynamic.Configuration
}{
{
desc: "empty configuration",
input: dynamic.Configuration{},
expected: dynamic.Configuration{},
},
{
desc: "without model",
input: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: make(map[string]*dynamic.Router),
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: make(map[string]*dynamic.Model),
},
},
expected: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: make(map[string]*dynamic.Router),
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: make(map[string]*dynamic.Model),
},
},
},
{
desc: "with model, not used",
input: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: make(map[string]*dynamic.Router),
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"ep@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
expected: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: make(map[string]*dynamic.Router),
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"ep@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
},
{
desc: "with model, one entry point",
input: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"websecure"},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"websecure@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
expected: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"websecure@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
},
{
desc: "with model, one entry point, and router with tls",
input: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"websecure"},
TLS: &dynamic.RouterTLSConfig{CertResolver: "router"},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"websecure@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{CertResolver: "ep"},
},
},
},
},
expected: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{CertResolver: "router"},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"websecure@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{CertResolver: "ep"},
},
},
},
},
},
{
desc: "with model, two entry points",
input: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"websecure", "web"},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"websecure@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
expected: dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{
"test": {
EntryPoints: []string{"web"},
},
"websecure-test": {
EntryPoints: []string{"websecure"},
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
Middlewares: make(map[string]*dynamic.Middleware),
Services: make(map[string]*dynamic.Service),
Models: map[string]*dynamic.Model{
"websecure@internal": {
Middlewares: []string{"test"},
TLS: &dynamic.RouterTLSConfig{},
},
},
},
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
actual := applyModel(test.input)
assert.Equal(t, test.expected, actual)
})
}
}

View file

@ -18,6 +18,8 @@ import (
type ConfigurationWatcher struct {
provider provider.Provider
entryPoints []string
providersThrottleDuration time.Duration
currentConfigurations safe.Safe
@ -32,7 +34,12 @@ type ConfigurationWatcher struct {
}
// NewConfigurationWatcher creates a new ConfigurationWatcher.
func NewConfigurationWatcher(routinesPool *safe.Pool, pvd provider.Provider, providersThrottleDuration time.Duration) *ConfigurationWatcher {
func NewConfigurationWatcher(
routinesPool *safe.Pool,
pvd provider.Provider,
providersThrottleDuration time.Duration,
entryPoints []string,
) *ConfigurationWatcher {
watcher := &ConfigurationWatcher{
provider: pvd,
configurationChan: make(chan dynamic.Message, 100),
@ -40,6 +47,7 @@ func NewConfigurationWatcher(routinesPool *safe.Pool, pvd provider.Provider, pro
providerConfigUpdateMap: make(map[string]chan dynamic.Message),
providersThrottleDuration: providersThrottleDuration,
routinesPool: routinesPool,
entryPoints: entryPoints,
}
currentConfigurations := make(dynamic.Configurations)
@ -135,7 +143,8 @@ func (c *ConfigurationWatcher) loadMessage(configMsg dynamic.Message) {
c.currentConfigurations.Set(newConfigurations)
conf := mergeConfiguration(newConfigurations)
conf := mergeConfiguration(newConfigurations, c.entryPoints)
conf = applyModel(conf)
for _, listener := range c.configurationListeners {
listener(conf)

View file

@ -55,7 +55,7 @@ func TestNewConfigurationWatcher(t *testing.T) {
}},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second)
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{})
run := make(chan struct{})
@ -112,7 +112,7 @@ func TestListenProvidersThrottleProviderConfigReload(t *testing.T) {
})
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond)
watcher := NewConfigurationWatcher(routinesPool, pvd, 30*time.Millisecond, []string{})
publishedConfigCount := 0
watcher.AddListener(func(_ dynamic.Configuration) {
@ -136,7 +136,7 @@ func TestListenProvidersSkipsEmptyConfigs(t *testing.T) {
messages: []dynamic.Message{{ProviderName: "mock"}},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second)
watcher := NewConfigurationWatcher(routinesPool, pvd, time.Second, []string{})
watcher.AddListener(func(_ dynamic.Configuration) {
t.Error("An empty configuration was published but it should not")
})
@ -162,7 +162,7 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
messages: []dynamic.Message{message, message},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 0)
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{})
alreadyCalled := false
watcher.AddListener(func(_ dynamic.Configuration) {
@ -205,7 +205,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond)
watcher := NewConfigurationWatcher(routinesPool, pvd, 15*time.Millisecond, []string{"defaultEP"})
var lastConfig dynamic.Configuration
watcher.AddListener(func(conf dynamic.Configuration) {
@ -220,7 +220,7 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock")),
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("defaultEP"))),
th.WithLoadBalancerServices(th.WithService("bar@mock")),
th.WithMiddlewares(),
),
@ -260,7 +260,7 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
},
}
watcher := NewConfigurationWatcher(routinesPool, pvd, 0)
watcher := NewConfigurationWatcher(routinesPool, pvd, 0, []string{"defaultEP"})
var publishedProviderConfig dynamic.Configuration
@ -276,7 +276,10 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
expected := dynamic.Configuration{
HTTP: th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo@mock"), th.WithRouter("foo@mock2")),
th.WithRouters(
th.WithRouter("foo@mock", th.WithEntryPoints("defaultEP")),
th.WithRouter("foo@mock2", th.WithEntryPoints("defaultEP")),
),
th.WithLoadBalancerServices(th.WithService("bar@mock"), th.WithService("bar@mock2")),
th.WithMiddlewares(),
),

View file

@ -76,28 +76,6 @@ func TestRouterManager_Get(t *testing.T) {
entryPoints: []string{"web"},
expected: expectedResult{StatusCode: http.StatusNotFound},
},
{
desc: "no middleware, default entry point",
routersConfig: map[string]*dynamic.Router{
"foo": {
Service: "foo-service",
Rule: "Host(`foo.bar`)",
},
},
serviceConfig: map[string]*dynamic.Service{
"foo-service": {
LoadBalancer: &dynamic.ServersLoadBalancer{
Servers: []dynamic.Server{
{
URL: server.URL,
},
},
},
},
},
entryPoints: []string{"web"},
expected: expectedResult{StatusCode: http.StatusOK},
},
{
desc: "no middleware, no matching",
routersConfig: map[string]*dynamic.Router{
@ -735,6 +713,14 @@ func TestRuntimeConfiguration(t *testing.T) {
func TestProviderOnMiddlewares(t *testing.T) {
entryPoints := []string{"web"}
staticCfg := static.Configuration{
EntryPoints: map[string]*static.EntryPoint{
"web": {
Address: ":80",
},
},
}
rtConf := runtime.NewConfig(dynamic.Configuration{
HTTP: &dynamic.HTTPConfiguration{
Services: map[string]*dynamic.Service{
@ -746,11 +732,13 @@ func TestProviderOnMiddlewares(t *testing.T) {
},
Routers: map[string]*dynamic.Router{
"router@file": {
EntryPoints: []string{"web"},
Rule: "Host(`test`)",
Service: "test@file",
Middlewares: []string{"chain@file", "m1"},
},
"router@docker": {
EntryPoints: []string{"web"},
Rule: "Host(`test`)",
Service: "test@file",
Middlewares: []string{"chain", "m1@file"},
@ -774,7 +762,7 @@ func TestProviderOnMiddlewares(t *testing.T) {
serviceManager := service.NewManager(rtConf.Services, http.DefaultTransport, nil, nil)
middlewaresBuilder := middleware.NewBuilder(rtConf.Middlewares, serviceManager)
responseModifierFactory := responsemodifiers.NewBuilder(map[string]*runtime.MiddlewareInfo{})
chainBuilder := middleware.NewChainBuilder(static.Configuration{}, nil, nil)
chainBuilder := middleware.NewChainBuilder(staticCfg, nil, nil)
routerManager := NewManager(rtConf, serviceManager, middlewaresBuilder, responseModifierFactory, chainBuilder)

View file

@ -23,17 +23,18 @@ func TestReuseService(t *testing.T) {
staticConfig := static.Configuration{
EntryPoints: map[string]*static.EntryPoint{
"http": {},
"web": {},
},
}
dynamicConfigs := th.BuildConfiguration(
th.WithRouters(
th.WithRouter("foo",
th.WithEntryPoints("web"),
th.WithServiceName("bar"),
th.WithRule("Path(`/ok`)")),
th.WithRouter("foo2",
th.WithEntryPoints("http"),
th.WithEntryPoints("web"),
th.WithRule("Path(`/unauthorized`)"),
th.WithServiceName("bar"),
th.WithRouterMiddlewares("basicauth")),
@ -56,7 +57,7 @@ func TestReuseService(t *testing.T) {
// Test that the /ok path returns a status 200.
responseRecorderOk := &httptest.ResponseRecorder{}
requestOk := httptest.NewRequest(http.MethodGet, testServer.URL+"/ok", nil)
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
@ -64,7 +65,7 @@ func TestReuseService(t *testing.T) {
// the basic authentication defined on the frontend.
responseRecorderUnauthorized := &httptest.ResponseRecorder{}
requestUnauthorized := httptest.NewRequest(http.MethodGet, testServer.URL+"/unauthorized", nil)
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorderUnauthorized, requestUnauthorized)
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderUnauthorized, requestUnauthorized)
assert.Equal(t, http.StatusUnauthorized, responseRecorderUnauthorized.Result().StatusCode, "status code")
}
@ -83,7 +84,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
config: func(testServerURL string) *dynamic.HTTPConfiguration {
return th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo",
th.WithEntryPoints("http"),
th.WithEntryPoints("web"),
th.WithServiceName("bar"),
th.WithRule(routeRule)),
),
@ -106,7 +107,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
config: func(testServerURL string) *dynamic.HTTPConfiguration {
return th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo",
th.WithEntryPoints("http"),
th.WithEntryPoints("web"),
th.WithServiceName("bar"),
th.WithRule(routeRule)),
),
@ -120,7 +121,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
config: func(testServerURL string) *dynamic.HTTPConfiguration {
return th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo",
th.WithEntryPoints("http"),
th.WithEntryPoints("web"),
th.WithServiceName("bar"),
th.WithRule(routeRule)),
),
@ -136,7 +137,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
config: func(testServerURL string) *dynamic.HTTPConfiguration {
return th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo",
th.WithEntryPoints("http"),
th.WithEntryPoints("web"),
th.WithServiceName("bar"),
th.WithRule(routeRule)),
),
@ -150,7 +151,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
config: func(testServerURL string) *dynamic.HTTPConfiguration {
return th.BuildConfiguration(
th.WithRouters(th.WithRouter("foo",
th.WithEntryPoints("http"),
th.WithEntryPoints("web"),
th.WithServiceName("bar"),
th.WithRule(routeRule)),
),
@ -176,7 +177,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
staticConfig := static.Configuration{
EntryPoints: map[string]*static.EntryPoint{
"http": {},
"web": {},
},
}
@ -190,7 +191,7 @@ func TestServerResponseEmptyBackend(t *testing.T) {
responseRecorder := &httptest.ResponseRecorder{}
request := httptest.NewRequest(http.MethodGet, testServer.URL+requestPath, nil)
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorder, request)
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorder, request)
assert.Equal(t, test.expectedStatusCode, responseRecorder.Result().StatusCode, "status code")
})
@ -206,13 +207,14 @@ func TestInternalServices(t *testing.T) {
staticConfig := static.Configuration{
API: &static.API{},
EntryPoints: map[string]*static.EntryPoint{
"http": {},
"web": {},
},
}
dynamicConfigs := th.BuildConfiguration(
th.WithRouters(
th.WithRouter("foo",
th.WithEntryPoints("web"),
th.WithServiceName("api@internal"),
th.WithRule("PathPrefix(`/api`)")),
),
@ -228,7 +230,7 @@ func TestInternalServices(t *testing.T) {
// Test that the /ok path returns a status 200.
responseRecorderOk := &httptest.ResponseRecorder{}
requestOk := httptest.NewRequest(http.MethodGet, testServer.URL+"/api/rawdata", nil)
entryPointsHandlers["http"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
}

View file

@ -53,6 +53,11 @@ func (m *InternalHandlers) BuildHTTP(rootCtx context.Context, serviceName string
func (m *InternalHandlers) get(serviceName string) (http.Handler, error) {
switch serviceName {
case "noop@internal":
return http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.WriteHeader(http.StatusTeapot)
}), nil
case "api@internal":
if m.api == nil {
return nil, errors.New("api is not enabled")