diff --git a/app/discovery/discovery.go b/app/discovery/discovery.go index a9e6f3d..10af668 100644 --- a/app/discovery/discovery.go +++ b/app/discovery/discovery.go @@ -6,6 +6,7 @@ package discovery import ( "context" + "log" "regexp" "sync" ) @@ -63,10 +64,14 @@ func (s *Service) Run(ctx context.Context) error { case <-ctx.Done(): return ctx.Err() case <-ch: - m := s.mergeLists() + log.Printf("[DEBUG] new update event received") + lst := s.mergeLists() + for _, m := range lst { + log.Printf("[INFO] match for %s: %s %s %s", m.ProviderID, m.Server, m.SrcMatch.String(), m.Dst) + } s.lock.Lock() - s.mappers = make([]UrlMapper, len(m)) - copy(s.mappers, m) + s.mappers = make([]UrlMapper, len(lst)) + copy(s.mappers, lst) s.lock.Unlock() } } diff --git a/app/discovery/discovery_test.go b/app/discovery/discovery_test.go index fea379f..8be8ee8 100644 --- a/app/discovery/discovery_test.go +++ b/app/discovery/discovery_test.go @@ -20,8 +20,8 @@ func TestService_Do(t *testing.T) { }, ListFunc: func() ([]UrlMapper, error) { return []UrlMapper{ - {SrcMatch: regexp.MustCompile("^/api/svc1/(.*)"), Dst: "http://127.0.0.1:8080/blah1/$1"}, - {SrcMatch: regexp.MustCompile("^/api/svc2/(.*)"), Dst: "http://127.0.0.2:8080/blah2/$1/abc"}, + {Server: "*", SrcMatch: regexp.MustCompile("^/api/svc1/(.*)"), Dst: "http://127.0.0.1:8080/blah1/$1"}, + {Server: "*", SrcMatch: regexp.MustCompile("^/api/svc2/(.*)"), Dst: "http://127.0.0.2:8080/blah2/$1/abc"}, }, nil }, IDFunc: func() ProviderID { @@ -34,7 +34,7 @@ func TestService_Do(t *testing.T) { }, ListFunc: func() ([]UrlMapper, error) { return []UrlMapper{ - {SrcMatch: regexp.MustCompile("/api/svc3/xyz"), Dst: "http://127.0.0.3:8080/blah3/xyz"}, + {Server: "localhost", SrcMatch: regexp.MustCompile("/api/svc3/xyz"), Dst: "http://127.0.0.3:8080/blah3/xyz"}, }, nil }, IDFunc: func() ProviderID { @@ -51,6 +51,7 @@ func TestService_Do(t *testing.T) { assert.Equal(t, context.DeadlineExceeded, err) assert.Equal(t, 3, len(svc.mappers)) assert.Equal(t, PIFile, svc.mappers[0].ProviderID) + assert.Equal(t, "*", svc.mappers[0].Server) assert.Equal(t, "^/api/svc1/(.*)", svc.mappers[0].SrcMatch.String()) assert.Equal(t, "http://127.0.0.1:8080/blah1/$1", svc.mappers[0].Dst) diff --git a/app/discovery/provider/docker.go b/app/discovery/provider/docker.go index b20fda0..01b1a40 100644 --- a/app/discovery/provider/docker.go +++ b/app/discovery/provider/docker.go @@ -7,7 +7,7 @@ import ( "strings" "time" - dclient "github.com/fsouza/go-dockerclient" + dc "github.com/fsouza/go-dockerclient" log "github.com/go-pkgz/lgr" "github.com/pkg/errors" @@ -16,7 +16,11 @@ import ( //go:generate moq -out docker_client_mock.go -skip-ensure -fmt goimports . DockerClient -// Docker emits all changes from all containers states +// Docker provide watch compatible changes from containers +// and maps by default from ^/api/%s/(.*) to http://%s:%d/$1, i.e. http://example.com/api/my_container/something +// will be mapped to http://172.17.42.1:8080/something. Ip will be the internal ip of the container and port - exposed the one +// Alternatively labels can alter this. dpx.route sets source route, and dpx.dest sets the destination. Optional dpx.server enforces +// match by server name (hostname). type Docker struct { DockerClient DockerClient Excludes []string @@ -25,8 +29,8 @@ type Docker struct { // DockerClient defines interface listing containers and subscribing to events type DockerClient interface { - ListContainers(opts dclient.ListContainersOptions) ([]dclient.APIContainers, error) - AddEventListener(listener chan<- *dclient.APIEvents) error + ListContainers(opts dc.ListContainersOptions) ([]dc.APIContainers, error) + AddEventListener(listener chan<- *dc.APIEvents) error } // containerInfo is simplified docker.APIEvents for containers only @@ -98,7 +102,7 @@ func (d *Docker) ID() discovery.ProviderID { return discovery.PIDocker } // activate starts blocking listener for all docker events // filters everything except "container" type, detects stop/start events and publishes signals to eventsCh func (d *Docker) events(ctx context.Context, client DockerClient, eventsCh chan struct{}) error { - dockerEventsCh := make(chan *dclient.APIEvents) + dockerEventsCh := make(chan *dc.APIEvents) if err := client.AddEventListener(dockerEventsCh); err != nil { return errors.Wrap(err, "can't add even listener") } @@ -132,14 +136,14 @@ func (d *Docker) events(ctx context.Context, client DockerClient, eventsCh chan func (d *Docker) listContainers() (res []containerInfo, err error) { - portExposed := func(c dclient.APIContainers) (int, bool) { + portExposed := func(c dc.APIContainers) (int, bool) { if len(c.Ports) == 0 { return 0, false } return int(c.Ports[0].PrivatePort), true } - containers, err := d.DockerClient.ListContainers(dclient.ListContainersOptions{All: false}) + containers, err := d.DockerClient.ListContainers(dc.ListContainersOptions{All: false}) if err != nil { return nil, errors.Wrap(err, "can't list containers") } diff --git a/app/discovery/provider/file.go b/app/discovery/provider/file.go index 6528bb7..20b8378 100644 --- a/app/discovery/provider/file.go +++ b/app/discovery/provider/file.go @@ -25,7 +25,7 @@ type File struct { func (d *File) Events(ctx context.Context) <-chan struct{} { res := make(chan struct{}) - // no need to queue multiple events or wait + // no need to queue multiple events trySubmit := func(ch chan struct{}) { select { case ch <- struct{}{}: diff --git a/app/discovery/provider/static.go b/app/discovery/provider/static.go index ed36480..e640807 100644 --- a/app/discovery/provider/static.go +++ b/app/discovery/provider/static.go @@ -12,7 +12,7 @@ import ( // Static provider, rules are server,from,to type Static struct { - Rules []string + Rules []string // each rule is 2 or 3 elements comma separated. [server,]source url,destination } // Events returns channel updating once