Migrate rest provider

This commit is contained in:
SALLEYRON Julien 2018-12-03 11:32:05 +01:00 committed by Traefiker Bot
parent 5d91c7e15c
commit c815a732ef
11 changed files with 185 additions and 4 deletions

View file

@ -19,10 +19,10 @@ import (
"github.com/containous/traefik/old/provider/marathon"
"github.com/containous/traefik/old/provider/mesos"
"github.com/containous/traefik/old/provider/rancher"
"github.com/containous/traefik/old/provider/rest"
"github.com/containous/traefik/old/provider/zk"
"github.com/containous/traefik/ping"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/provider/rest"
"github.com/containous/traefik/tracing/datadog"
"github.com/containous/traefik/tracing/jaeger"
"github.com/containous/traefik/tracing/zipkin"

View file

@ -20,11 +20,11 @@ import (
"github.com/containous/traefik/old/provider/marathon"
"github.com/containous/traefik/old/provider/mesos"
"github.com/containous/traefik/old/provider/rancher"
"github.com/containous/traefik/old/provider/rest"
"github.com/containous/traefik/old/provider/zk"
"github.com/containous/traefik/ping"
acmeprovider "github.com/containous/traefik/provider/acme"
"github.com/containous/traefik/provider/file"
"github.com/containous/traefik/provider/rest"
"github.com/containous/traefik/tls"
"github.com/containous/traefik/tracing/datadog"
"github.com/containous/traefik/tracing/jaeger"

View file

@ -0,0 +1,12 @@
[entryPoints]
[entryPoints.http]
address = ":8000"
[api]
[log]
logLevel = "DEBUG"
[providers]
[providers.rest]

View file

@ -60,6 +60,7 @@ func init() {
check.Suite(&AcmeSuite{})
check.Suite(&ErrorPagesSuite{})
check.Suite(&FileSuite{})
check.Suite(&RestSuite{})
check.Suite(&GRPCSuite{})
check.Suite(&HealthCheckSuite{})
check.Suite(&HTTPSSuite{})

View file

@ -0,0 +1,4 @@
whoami1:
image: containous/whoami
ports:
- "8881:80"

73
integration/rest_test.go Normal file
View file

@ -0,0 +1,73 @@
package integration
import (
"bytes"
"encoding/json"
"net/http"
"time"
"github.com/containous/traefik/config"
"github.com/containous/traefik/integration/try"
"github.com/go-check/check"
checker "github.com/vdemeester/shakers"
)
type RestSuite struct{ BaseSuite }
func (s *RestSuite) SetUpSuite(c *check.C) {
s.createComposeProject(c, "rest")
s.composeProject.Start(c)
}
func (s *RestSuite) TestSimpleConfiguration(c *check.C) {
cmd, display := s.traefikCmd(withConfigFile("fixtures/rest/simple.toml"))
defer display(c)
err := cmd.Start()
c.Assert(err, checker.IsNil)
defer cmd.Process.Kill()
// Expected a 404 as we did not configure anything.
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusNotFound))
c.Assert(err, checker.IsNil)
config := config.Configuration{
Routers: map[string]*config.Router{
"router1": {
EntryPoints: []string{"http"},
Middlewares: []string{},
Service: "service1",
Rule: "PathPrefix:/",
},
},
Services: map[string]*config.Service{
"service1": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://" + s.composeProject.Container(c, "whoami1").NetworkSettings.IPAddress + ":80",
Weight: 1,
},
},
},
},
},
}
json, err := json.Marshal(config)
c.Assert(err, checker.IsNil)
request, err := http.NewRequest(http.MethodPut, "http://127.0.0.1:8080/api/providers/rest", bytes.NewReader(json))
c.Assert(err, checker.IsNil)
response, err := http.DefaultClient.Do(request)
c.Assert(err, checker.IsNil)
c.Assert(response.StatusCode, checker.Equals, http.StatusOK)
err = try.GetRequest("http://127.0.0.1:8080/api/providers/rest/routers", 1000*time.Millisecond, try.BodyContains("PathPrefix:/"))
c.Assert(err, checker.IsNil)
err = try.GetRequest("http://127.0.0.1:8000/", 1000*time.Millisecond, try.StatusCodeIs(http.StatusOK))
c.Assert(err, checker.IsNil)
}

View file

@ -23,6 +23,10 @@ func NewProviderAggregator(conf static.Providers) ProviderAggregator {
p.quietAddProvider(conf.File)
}
if conf.Rest != nil {
p.quietAddProvider(conf.Rest)
}
return p
}

67
provider/rest/rest.go Normal file
View file

@ -0,0 +1,67 @@
package rest
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/containous/mux"
"github.com/containous/traefik/config"
"github.com/containous/traefik/log"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/safe"
"github.com/unrolled/render"
)
var _ provider.Provider = (*Provider)(nil)
// Provider is a provider.Provider implementation that provides a Rest API.
type Provider struct {
configurationChan chan<- config.Message
EntryPoint string `description:"EntryPoint" export:"true"`
}
var templatesRenderer = render.New(render.Options{Directory: "nowhere"})
// Init the provider.
func (p *Provider) Init() error {
return nil
}
// Append add rest provider routes on a router.
func (p *Provider) Append(systemRouter *mux.Router) {
systemRouter.
Methods(http.MethodPut).
Path("/api/providers/{provider}").
HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
if vars["provider"] != "rest" {
response.WriteHeader(http.StatusBadRequest)
fmt.Fprint(response, "Only 'rest' provider can be updated through the REST API")
return
}
configuration := new(config.Configuration)
body, _ := ioutil.ReadAll(request.Body)
err := json.Unmarshal(body, configuration)
if err == nil {
p.configurationChan <- config.Message{ProviderName: "rest", Configuration: configuration}
err := templatesRenderer.JSON(response, http.StatusOK, configuration)
if err != nil {
log.WithoutContext().Error(err)
}
} else {
log.WithoutContext().Errorf("Error parsing configuration %+v", err)
http.Error(response, fmt.Sprintf("%+v", err), http.StatusBadRequest)
}
})
}
// Provide allows the provider to provide configurations to traefik
// using the given configuration channel.
func (p *Provider) Provide(configurationChan chan<- config.Message, pool *safe.Pool) error {
p.configurationChan = configurationChan
return nil
}

View file

@ -24,7 +24,9 @@ func NewRouteAppenderAggregator(ctx context.Context, chainBuilder chainBuilder,
aggregator := &RouteAppenderAggregator{}
// FIXME add REST
if conf.Providers != nil && conf.Providers.Rest != nil {
aggregator.AddAppender(conf.Providers.Rest)
}
if conf.API != nil && conf.API.EntryPoint == entryPointName {
chain, err := chainBuilder.BuildChain(ctx, conf.API.Middlewares)

View file

@ -59,6 +59,21 @@ func TestRouterManager_Get(t *testing.T) {
entryPoints: []string{"web"},
expected: ExpectedResult{StatusCode: http.StatusOK},
},
{
desc: "no load balancer",
routersConfig: map[string]*config.Router{
"foo": {
EntryPoints: []string{"web"},
Service: "foo-service",
Rule: "Host:foo.bar",
},
},
serviceConfig: map[string]*config.Service{
"foo-service": {},
},
entryPoints: []string{"web"},
expected: ExpectedResult{StatusCode: http.StatusNotFound},
},
{
desc: "no middleware, default entry point",
routersConfig: map[string]*config.Router{

View file

@ -61,7 +61,10 @@ func (m *Manager) Build(rootCtx context.Context, serviceName string, responseMod
// TODO refactor ?
if conf, ok := m.configs[serviceName]; ok {
// FIXME Should handle multiple service types
return m.getLoadBalancerServiceHandler(ctx, serviceName, conf.LoadBalancer, responseModifier)
if conf.LoadBalancer != nil {
return m.getLoadBalancerServiceHandler(ctx, serviceName, conf.LoadBalancer, responseModifier)
}
return nil, fmt.Errorf("the service %q doesn't have any load balancer", serviceName)
}
return nil, fmt.Errorf("the service %q does not exits", serviceName)
}