Codebase list golang-github-go-kit-kit / 443f6ea
Refactoring without client intermediary Martin Baillie 6 years ago
8 changed file(s) with 371 addition(s) and 335 deletion(s). Raw diff Collapse all Expand all
+0
-77
sd/eureka/client.go less more
0 package eureka
1
2 import (
3 "github.com/hudl/fargo"
4 )
5
6 // Client is a wrapper around the Eureka API.
7 type Client interface {
8 // Register an instance with Eureka.
9 Register(i *fargo.Instance) error
10
11 // Deregister an instance from Eureka.
12 Deregister(i *fargo.Instance) error
13
14 // Send an instance heartbeat to Eureka.
15 Heartbeat(i *fargo.Instance) error
16
17 // Get all instances for an app in Eureka.
18 Instances(app string) ([]*fargo.Instance, error)
19
20 // Receive scheduled updates about an app's instances in Eureka.
21 ScheduleUpdates(app string, quitc chan struct{}) <-chan fargo.AppUpdate
22 }
23
24 type client struct {
25 connection *fargo.EurekaConnection
26 }
27
28 // NewClient returns an implementation of the Client interface, wrapping a
29 // concrete connection to Eureka using the Fargo library.
30 // Taking in Fargo's own connection abstraction gives the user maximum
31 // freedom in regards to how that connection is configured.
32 func NewClient(ec *fargo.EurekaConnection) Client {
33 return &client{connection: ec}
34 }
35
36 func (c *client) Register(i *fargo.Instance) error {
37 if c.instanceRegistered(i) {
38 // Already registered. Send a heartbeat instead.
39 return c.Heartbeat(i)
40 }
41 return c.connection.RegisterInstance(i)
42 }
43
44 func (c *client) Deregister(i *fargo.Instance) error {
45 return c.connection.DeregisterInstance(i)
46 }
47
48 func (c *client) Heartbeat(i *fargo.Instance) (err error) {
49 if err = c.connection.HeartBeatInstance(i); err != nil && c.instanceNotFoundErr(err) {
50 // Instance not registered. Register first before sending heartbeats.
51 return c.Register(i)
52 }
53 return err
54 }
55
56 func (c *client) Instances(app string) ([]*fargo.Instance, error) {
57 stdApp, err := c.connection.GetApp(app)
58 if err != nil {
59 return nil, err
60 }
61 return stdApp.Instances, nil
62 }
63
64 func (c *client) ScheduleUpdates(app string, quitc chan struct{}) <-chan fargo.AppUpdate {
65 return c.connection.ScheduleAppUpdates(app, false, quitc)
66 }
67
68 func (c *client) instanceRegistered(i *fargo.Instance) bool {
69 _, err := c.connection.GetInstance(i.App, i.Id())
70 return err == nil
71 }
72
73 func (c *client) instanceNotFoundErr(err error) bool {
74 code, ok := fargo.HTTPResponseStatusCode(err)
75 return ok && code == 404
76 }
+0
-95
sd/eureka/client_test.go less more
0 package eureka
1
2 import (
3 "errors"
4 "reflect"
5
6 "github.com/hudl/fargo"
7
8 "github.com/go-kit/kit/log"
9 )
10
11 var (
12 errTest = errors.New("kaboom")
13 loggerTest = log.NewNopLogger()
14 instanceTest1 = &fargo.Instance{
15 HostName: "server1.acme.org",
16 Port: 8080,
17 App: "go-kit",
18 IPAddr: "192.168.0.1",
19 VipAddress: "192.168.0.1",
20 SecureVipAddress: "192.168.0.1",
21 HealthCheckUrl: "http://server1.acme.org:8080/healthz",
22 StatusPageUrl: "http://server1.acme.org:8080/status",
23 HomePageUrl: "http://server1.acme.org:8080/",
24 Status: fargo.UP,
25 DataCenterInfo: fargo.DataCenterInfo{Name: fargo.MyOwn},
26 LeaseInfo: fargo.LeaseInfo{RenewalIntervalInSecs: 1},
27 }
28 instanceTest2 = &fargo.Instance{
29 HostName: "server2.acme.org",
30 Port: 8080,
31 App: "go-kit",
32 IPAddr: "192.168.0.2",
33 VipAddress: "192.168.0.2",
34 SecureVipAddress: "192.168.0.2",
35 HealthCheckUrl: "http://server2.acme.org:8080/healthz",
36 StatusPageUrl: "http://server2.acme.org:8080/status",
37 HomePageUrl: "http://server2.acme.org:8080/",
38 Status: fargo.UP,
39 DataCenterInfo: fargo.DataCenterInfo{Name: fargo.MyOwn},
40 }
41 applicationTest = &fargo.Application{
42 Name: "go-kit",
43 Instances: []*fargo.Instance{instanceTest1, instanceTest2},
44 }
45 )
46
47 type testClient struct {
48 instances []*fargo.Instance
49 application *fargo.Application
50 errInstances error
51 errApplication error
52 errHeartbeat error
53 }
54
55 func (c *testClient) Register(i *fargo.Instance) error {
56 for _, instance := range c.instances {
57 if reflect.DeepEqual(*instance, *i) {
58 return errors.New("already registered")
59 }
60 }
61
62 c.instances = append(c.instances, i)
63 return nil
64 }
65
66 func (c *testClient) Deregister(i *fargo.Instance) error {
67 var newInstances []*fargo.Instance
68 for _, instance := range c.instances {
69 if reflect.DeepEqual(*instance, *i) {
70 continue
71 }
72 newInstances = append(newInstances, instance)
73 }
74 if len(newInstances) == len(c.instances) {
75 return errors.New("not registered")
76 }
77
78 c.instances = newInstances
79 return nil
80 }
81
82 func (c *testClient) Heartbeat(i *fargo.Instance) (err error) {
83 return c.errHeartbeat
84 }
85
86 func (c *testClient) Instances(app string) ([]*fargo.Instance, error) {
87 return c.instances, c.errInstances
88 }
89
90 func (c *testClient) ScheduleUpdates(service string, quitc chan struct{}) <-chan fargo.AppUpdate {
91 updatec := make(chan fargo.AppUpdate, 1)
92 updatec <- fargo.AppUpdate{App: c.application, Err: c.errApplication}
93 return updatec
94 }
2828 t.Skip("EUREKA_ADDR is not set")
2929 }
3030
31 var client Client
32 {
33 var fargoConfig fargo.Config
34 fargoConfig.Eureka.ServiceUrls = []string{eurekaAddr}
35 fargoConfig.Eureka.PollIntervalSeconds = 1
36
37 fargoConnection := fargo.NewConnFromConfig(fargoConfig)
38 client = NewClient(&fargoConnection)
39 }
40
4131 logger := log.NewLogfmtLogger(os.Stderr)
4232 logger = log.With(logger, "ts", log.DefaultTimestamp)
4333
34 var fargoConfig fargo.Config
35 // Target Eureka server(s).
36 fargoConfig.Eureka.ServiceUrls = []string{eurekaAddr}
37 // How often the subscriber should poll for updates.
38 fargoConfig.Eureka.PollIntervalSeconds = 1
39
40 // Create a Fargo connection and a Eureka registrar.
41 fargoConnection := fargo.NewConnFromConfig(fargoConfig)
42 registrar1 := NewRegistrar(&fargoConnection, instanceTest1, log.With(logger, "component", "registrar1"))
43
4444 // Register one instance.
45 registrar1 := NewRegistrar(client, instanceTest1, log.With(logger, "component", "registrar1"))
4645 registrar1.Register()
4746 defer registrar1.Deregister()
4847
4948 // This should be enough time for the Eureka server response cache to update.
5049 time.Sleep(time.Second)
5150
52 // Build a subscriber.
51 // Build a Eureka subscriber.
5352 factory := func(instance string) (endpoint.Endpoint, io.Closer, error) {
5453 t.Logf("factory invoked for %q", instance)
5554 return endpoint.Nop, nil, nil
5655 }
5756 s := NewSubscriber(
58 client,
57 &fargoConnection,
58 appNameTest,
5959 factory,
6060 log.With(logger, "component", "subscriber"),
61 instanceTest1.App,
6261 )
6362 defer s.Stop()
6463
7271 }
7372
7473 // Register a second instance
75 registrar2 := NewRegistrar(client, instanceTest2, log.With(logger, "component", "registrar2"))
74 registrar2 := NewRegistrar(&fargoConnection, instanceTest2, log.With(logger, "component", "registrar2"))
7675 registrar2.Register()
7776 defer registrar2.Deregister() // In case of exceptional circumstances.
7877
11
22 import (
33 "fmt"
4 "net/http"
45 "sync"
56 "time"
67
78 "github.com/hudl/fargo"
89
910 "github.com/go-kit/kit/log"
11 "github.com/go-kit/kit/sd"
1012 )
13
14 // Matches official Netflix Java client default.
15 const defaultRenewalInterval = 30 * time.Second
16
17 // The methods of fargo.Connection used in this package.
18 type fargoConnection interface {
19 RegisterInstance(instance *fargo.Instance) error
20 DeregisterInstance(instance *fargo.Instance) error
21 ReregisterInstance(instance *fargo.Instance) error
22 HeartBeatInstance(instance *fargo.Instance) error
23 ScheduleAppUpdates(name string, await bool, done <-chan struct{}) <-chan fargo.AppUpdate
24 GetApp(name string) (*fargo.Application, error)
25 }
26
27 type fargoUnsuccessfulHTTPResponse struct {
28 statusCode int
29 messagePrefix string
30 }
1131
1232 // Registrar maintains service instance liveness information in Eureka.
1333 type Registrar struct {
14 client Client
34 conn fargoConnection
1535 instance *fargo.Instance
1636 logger log.Logger
17 quit chan struct{}
18 wg sync.WaitGroup
37 quitc chan chan struct{}
38 sync.Mutex
1939 }
2040
41 var _ sd.Registrar = (*Registrar)(nil)
42
2143 // NewRegistrar returns an Eureka Registrar acting on behalf of the provided
22 // Fargo instance.
23 func NewRegistrar(client Client, i *fargo.Instance, logger log.Logger) *Registrar {
44 // Fargo connection and instance. See the integration test for usage examples.
45 func NewRegistrar(conn fargoConnection, instance *fargo.Instance, logger log.Logger) *Registrar {
2446 return &Registrar{
25 client: client,
26 instance: i,
27 logger: log.With(logger, "service", i.App, "address", fmt.Sprintf("%s:%d", i.IPAddr, i.Port)),
47 conn: conn,
48 instance: instance,
49 logger: log.With(logger, "service", instance.App, "address", fmt.Sprintf("%s:%d", instance.IPAddr, instance.Port)),
2850 }
2951 }
3052
31 // Register implements sd.Registrar interface.
53 // Register implements sd.Registrar.
3254 func (r *Registrar) Register() {
33 if err := r.client.Register(r.instance); err != nil {
34 r.logger.Log("err", err)
35 } else {
36 r.logger.Log("action", "register")
55 r.Lock()
56 defer r.Unlock()
57
58 if r.quitc != nil {
59 return // Already in the registration loop.
3760 }
3861
62 if err := r.conn.RegisterInstance(r.instance); err != nil {
63 r.logger.Log("during", "Register", "err", err)
64 }
65
66 r.quitc = make(chan chan struct{})
67 go r.loop()
68 }
69
70 // Deregister implements sd.Registrar.
71 func (r *Registrar) Deregister() {
72 r.Lock()
73 defer r.Unlock()
74
75 if r.quitc == nil {
76 return // Already deregistered.
77 }
78
79 q := make(chan struct{})
80 r.quitc <- q
81 <-q
82 r.quitc = nil
83 }
84
85 func (r *Registrar) loop() {
86 var renewalInterval time.Duration
3987 if r.instance.LeaseInfo.RenewalIntervalInSecs > 0 {
40 // User has opted for heartbeat functionality in Eureka.
41 if r.quit == nil {
42 r.quit = make(chan struct{})
43 r.wg.Add(1)
44 go r.loop()
88 renewalInterval = time.Duration(r.instance.LeaseInfo.RenewalIntervalInSecs) * time.Second
89 } else {
90 renewalInterval = defaultRenewalInterval
91 }
92 ticker := time.NewTicker(renewalInterval)
93 defer ticker.Stop()
94
95 for {
96 select {
97 case <-ticker.C:
98 if err := r.heartbeat(); err != nil {
99 r.logger.Log("during", "heartbeat", "err", err)
100 }
101
102 case q := <-r.quitc:
103 if err := r.conn.DeregisterInstance(r.instance); err != nil {
104 r.logger.Log("during", "Deregister", "err", err)
105 }
106 close(q)
107 return
45108 }
46109 }
47110 }
48111
49 // Deregister implements sd.Registrar interface.
50 func (r *Registrar) Deregister() {
51 if err := r.client.Deregister(r.instance); err != nil {
52 r.logger.Log("err", err)
53 } else {
54 r.logger.Log("action", "deregister")
112 func (r *Registrar) heartbeat() error {
113 err := r.conn.HeartBeatInstance(r.instance)
114 if err != nil {
115 if u, ok := err.(*fargoUnsuccessfulHTTPResponse); ok && u.statusCode == http.StatusNotFound {
116 // Instance expired (e.g. network partition). Re-register.
117 r.logger.Log("during", "heartbeat", err.Error())
118 return r.conn.ReregisterInstance(r.instance)
119 }
55120 }
56
57 if r.quit != nil {
58 close(r.quit)
59 r.wg.Wait()
60 r.quit = nil
61 }
121 return err
62122 }
63123
64 func (r *Registrar) loop() {
65 tick := time.NewTicker(time.Duration(r.instance.LeaseInfo.RenewalIntervalInSecs) * time.Second)
66 defer tick.Stop()
67 defer r.wg.Done()
68
69 for {
70 select {
71 case <-tick.C:
72 if err := r.client.Heartbeat(r.instance); err != nil {
73 r.logger.Log("err", err)
74 }
75 case <-r.quit:
76 return
77 }
78 }
124 func (u *fargoUnsuccessfulHTTPResponse) Error() string {
125 return fmt.Sprintf("err=%s code=%d", u.messagePrefix, u.statusCode)
79126 }
22 import (
33 "testing"
44 "time"
5
6 "github.com/hudl/fargo"
75 )
86
97 func TestRegistrar(t *testing.T) {
10 client := &testClient{
11 instances: []*fargo.Instance{},
8 connection := &testConnection{
129 errHeartbeat: errTest,
1310 }
1411
15 r := NewRegistrar(client, instanceTest1, loggerTest)
16 if want, have := 0, len(client.instances); want != have {
17 t.Errorf("want %d, have %d", want, have)
18 }
12 registrar1 := NewRegistrar(connection, instanceTest1, loggerTest)
13 registrar2 := NewRegistrar(connection, instanceTest2, loggerTest)
1914
2015 // Not registered.
21 r.Deregister()
22 if want, have := 0, len(client.instances); want != have {
16 registrar1.Deregister()
17 if want, have := 0, len(connection.instances); want != have {
2318 t.Errorf("want %d, have %d", want, have)
2419 }
2520
2621 // Register.
27 r.Register()
28 if want, have := 1, len(client.instances); want != have {
22 registrar1.Register()
23 if want, have := 1, len(connection.instances); want != have {
24 t.Errorf("want %d, have %d", want, have)
25 }
26
27 registrar2.Register()
28 if want, have := 2, len(connection.instances); want != have {
2929 t.Errorf("want %d, have %d", want, have)
3030 }
3131
3232 // Deregister.
33 r.Deregister()
34 if want, have := 0, len(client.instances); want != have {
33 registrar1.Deregister()
34 if want, have := 1, len(connection.instances); want != have {
3535 t.Errorf("want %d, have %d", want, have)
3636 }
3737
3838 // Already registered.
39 r.Register()
40 if want, have := 1, len(client.instances); want != have {
39 registrar1.Register()
40 if want, have := 2, len(connection.instances); want != have {
4141 t.Errorf("want %d, have %d", want, have)
4242 }
43 r.Register()
44 if want, have := 1, len(client.instances); want != have {
43 registrar1.Register()
44 if want, have := 2, len(connection.instances); want != have {
4545 t.Errorf("want %d, have %d", want, have)
4646 }
4747
4848 // Wait for a heartbeat failure.
49 time.Sleep(time.Second)
50 if want, have := 1, len(client.instances); want != have {
49 time.Sleep(1010 * time.Millisecond)
50 if want, have := 2, len(connection.instances); want != have {
5151 t.Errorf("want %d, have %d", want, have)
5252 }
53 r.Deregister()
54 if want, have := 0, len(client.instances); want != have {
53 registrar1.Deregister()
54 if want, have := 1, len(connection.instances); want != have {
5555 t.Errorf("want %d, have %d", want, have)
5656 }
5757 }
58
59 func TestBadRegister(t *testing.T) {
60 connection := &testConnection{
61 errRegister: errTest,
62 }
63
64 registrar := NewRegistrar(connection, instanceTest1, loggerTest)
65 registrar.Register()
66 if want, have := 0, len(connection.instances); want != have {
67 t.Errorf("want %d, have %d", want, have)
68 }
69 }
70
71 func TestBadDeregister(t *testing.T) {
72 connection := &testConnection{
73 errDeregister: errTest,
74 }
75
76 registrar := NewRegistrar(connection, instanceTest1, loggerTest)
77 registrar.Register()
78 if want, have := 1, len(connection.instances); want != have {
79 t.Errorf("want %d, have %d", want, have)
80 }
81 registrar.Deregister()
82 if want, have := 1, len(connection.instances); want != have {
83 t.Errorf("want %d, have %d", want, have)
84 }
85 }
86
87 func TestExpiredInstance(t *testing.T) {
88 connection := &testConnection{
89 errHeartbeat: errNotFound,
90 }
91
92 registrar := NewRegistrar(connection, instanceTest1, loggerTest)
93 registrar.Register()
94
95 // Wait for a heartbeat failure.
96 time.Sleep(1010 * time.Millisecond)
97
98 if want, have := 1, len(connection.instances); want != have {
99 t.Errorf("want %d, have %d", want, have)
100 }
101 }
1313 // Subscriber yields endpoints stored in the Eureka registry for the given app.
1414 // Changes in that app are watched and will update the Subscriber endpoints.
1515 type Subscriber struct {
16 client Client
17 cache *cache.Cache
18 logger log.Logger
19 app string
20 quitc chan struct{}
16 conn fargoConnection
17 app string
18 factory sd.Factory
19 logger log.Logger
20 cache *cache.Cache
21 quitc chan chan struct{}
2122 }
2223
23 var _ sd.Subscriber = &Subscriber{}
24 var _ sd.Subscriber = (*Subscriber)(nil)
2425
2526 // NewSubscriber returns a Eureka subscriber. It will start watching the given
2627 // app string for changes, and update the endpoints accordingly.
27 func NewSubscriber(c Client, factory sd.Factory, logger log.Logger, app string) *Subscriber {
28 func NewSubscriber(conn fargoConnection, app string, factory sd.Factory, logger log.Logger) *Subscriber {
29 logger = log.With(logger, "app", app)
30
2831 s := &Subscriber{
29 client: c,
30 cache: cache.New(factory, logger),
31 app: app,
32 logger: logger,
33 quitc: make(chan struct{}),
32 conn: conn,
33 app: app,
34 factory: factory,
35 logger: logger,
36 cache: cache.New(factory, logger),
37 quitc: make(chan chan struct{}),
3438 }
3539
3640 instances, err := s.getInstances()
3741 if err == nil {
38 s.logger.Log("app", s.app, "instances", len(instances))
42 s.logger.Log("instances", len(instances))
3943 } else {
40 s.logger.Log("app", s.app, "msg", "failed to retrieve instances", "err", err)
44 s.logger.Log("during", "getInstances", "err", err)
4145 }
4246
4347 s.cache.Update(instances)
4549 return s
4650 }
4751
48 func (s *Subscriber) getInstances() ([]string, error) {
49 fargoInstances, err := s.client.Instances(s.app)
50 if err != nil {
51 return nil, err
52 }
53 return convertFargoInstances(fargoInstances), nil
54 }
55
56 func (s *Subscriber) loop() {
57 updatec := s.client.ScheduleUpdates(s.app, s.quitc)
58 for {
59 select {
60 case <-s.quitc:
61 return
62 case u := <-updatec:
63 if u.Err != nil {
64 s.logger.Log("app", s.app, "msg", "failed to retrieve instances", "err", u.Err)
65 continue
66 }
67
68 instances := convertFargoApplication(u.App)
69 s.logger.Log("app", s.app, "instances", len(instances))
70 s.cache.Update(instances)
71 }
72 }
73 }
74
7552 // Endpoints implements the Subscriber interface.
7653 func (s *Subscriber) Endpoints() ([]endpoint.Endpoint, error) {
7754 return s.cache.Endpoints(), nil
7855 }
7956
80 // Stop terminates the Subscriber.
57 // Stop terminates the subscriber.
8158 func (s *Subscriber) Stop() {
82 close(s.quitc)
59 q := make(chan struct{})
60 s.quitc <- q
61 <-q
62 s.quitc = nil
8363 }
8464
85 func convertFargoApplication(fargoApplication *fargo.Application) (instances []string) {
86 if fargoApplication != nil {
87 instances = convertFargoInstances(fargoApplication.Instances)
65 func (s *Subscriber) loop() {
66 var (
67 await = false
68 done = make(chan struct{})
69 updatec = s.conn.ScheduleAppUpdates(s.app, await, done)
70 )
71 defer close(done)
72
73 for {
74 select {
75 case update := <-updatec:
76 if update.Err != nil {
77 s.logger.Log("during", "Update", "err", update.Err)
78 continue
79 }
80 instances := convertFargoAppToInstances(update.App)
81 s.logger.Log("instances", len(instances))
82 s.cache.Update(instances)
83
84 case q := <-s.quitc:
85 close(q)
86 return
87 }
88 }
89 }
90
91 func (s *Subscriber) getInstances() ([]string, error) {
92 app, err := s.conn.GetApp(s.app)
93 if err != nil {
94 return nil, err
95 }
96 return convertFargoAppToInstances(app), nil
97 }
98
99 func convertFargoAppToInstances(app *fargo.Application) []string {
100 instances := make([]string, len(app.Instances))
101 for i, inst := range app.Instances {
102 instances[i] = fmt.Sprintf("%s:%d", inst.IPAddr, inst.Port)
88103 }
89104 return instances
90105 }
91
92 func convertFargoInstances(fargoInstances []*fargo.Instance) []string {
93 instances := make([]string, len(fargoInstances))
94 for i, fargoInstance := range fargoInstances {
95 instances[i] = fmt.Sprintf("%s:%d", fargoInstance.IPAddr, fargoInstance.Port)
96 }
97 return instances
98 }
1414 return endpoint.Nop, nil, nil
1515 }
1616
17 client := &testClient{
17 connection := &testConnection{
1818 instances: []*fargo.Instance{instanceTest1},
19 application: applicationTest,
19 application: appUpdateTest,
2020 errApplication: nil,
2121 }
2222
23 s := NewSubscriber(client, factory, loggerTest, instanceTest1.App)
24 defer s.Stop()
23 subscriber := NewSubscriber(connection, appNameTest, factory, loggerTest)
24 defer subscriber.Stop()
2525
26 endpoints, err := s.Endpoints()
26 endpoints, err := subscriber.Endpoints()
2727 if err != nil {
2828 t.Fatal(err)
2929 }
3838 return endpoint.Nop, nil, nil
3939 }
4040
41 client := &testClient{
41 connection := &testConnection{
4242 instances: []*fargo.Instance{instanceTest1},
43 application: applicationTest,
43 application: appUpdateTest,
4444 errApplication: nil,
4545 }
4646
47 s := NewSubscriber(client, factory, loggerTest, instanceTest1.App)
48 defer s.Stop()
47 subscriber := NewSubscriber(connection, appNameTest, factory, loggerTest)
48 defer subscriber.Stop()
4949
50 endpoints, _ := s.Endpoints()
50 endpoints, _ := subscriber.Endpoints()
5151 if want, have := 1, len(endpoints); want != have {
5252 t.Errorf("want %d, have %d", want, have)
5353 }
5454
5555 time.Sleep(50 * time.Millisecond)
5656
57 endpoints, _ = s.Endpoints()
57 endpoints, _ = subscriber.Endpoints()
5858 if want, have := 2, len(endpoints); want != have {
5959 t.Errorf("want %v, have %v", want, have)
6060 }
6565 return nil, nil, errTest
6666 }
6767
68 client := &testClient{
69 instances: []*fargo.Instance{instanceTest1},
68 connection := &testConnection{
69 instances: []*fargo.Instance{instanceTest1},
70 application: appUpdateTest,
71 errApplication: nil,
7072 }
7173
72 s := NewSubscriber(client, factory, loggerTest, instanceTest1.App)
73 defer s.Stop()
74 subscriber := NewSubscriber(connection, appNameTest, factory, loggerTest)
75 defer subscriber.Stop()
7476
75 endpoints, err := s.Endpoints()
77 endpoints, err := subscriber.Endpoints()
7678 if err != nil {
7779 t.Fatal(err)
7880 }
8789 return endpoint.Nop, nil, nil
8890 }
8991
90 client := &testClient{
92 connection := &testConnection{
93 instances: []*fargo.Instance{},
9194 errInstances: errTest,
92 application: applicationTest,
95 application: appUpdateTest,
9396 errApplication: nil,
9497 }
9598
96 s := NewSubscriber(client, factory, loggerTest, instanceTest1.App)
97 defer s.Stop()
99 subscriber := NewSubscriber(connection, appNameTest, factory, loggerTest)
100 defer subscriber.Stop()
98101
99 endpoints, err := s.Endpoints()
102 endpoints, err := subscriber.Endpoints()
100103 if err != nil {
101104 t.Fatal(err)
102105 }
111114 return endpoint.Nop, nil, nil
112115 }
113116
114 client := &testClient{
117 connection := &testConnection{
115118 instances: []*fargo.Instance{instanceTest1},
116 application: applicationTest,
119 application: appUpdateTest,
117120 errApplication: errTest,
118121 }
119122
120 s := NewSubscriber(client, factory, loggerTest, instanceTest1.App)
121 defer s.Stop()
123 subscriber := NewSubscriber(connection, appNameTest, factory, loggerTest)
124 defer subscriber.Stop()
122125
123 endpoints, err := s.Endpoints()
126 endpoints, err := subscriber.Endpoints()
124127 if err != nil {
125128 t.Error(err)
126129 }
130133
131134 time.Sleep(50 * time.Millisecond)
132135
133 endpoints, err = s.Endpoints()
136 endpoints, err = subscriber.Endpoints()
134137 if err != nil {
135138 t.Error(err)
136139 }
0 package eureka
1
2 import (
3 "errors"
4 "reflect"
5
6 "github.com/go-kit/kit/log"
7 "github.com/hudl/fargo"
8 )
9
10 type testConnection struct {
11 instances []*fargo.Instance
12 application *fargo.Application
13 errInstances error
14 errApplication error
15 errHeartbeat error
16 errRegister error
17 errDeregister error
18 }
19
20 var (
21 errTest = errors.New("kaboom")
22 errNotFound = &fargoUnsuccessfulHTTPResponse{statusCode: 404, messagePrefix: "not found"}
23 loggerTest = log.NewNopLogger()
24 appNameTest = "go-kit"
25 appUpdateTest = &fargo.Application{
26 Name: appNameTest,
27 Instances: []*fargo.Instance{instanceTest1, instanceTest2},
28 }
29 instanceTest1 = &fargo.Instance{
30 HostName: "serveregistrar1.acme.org",
31 Port: 8080,
32 App: appNameTest,
33 IPAddr: "192.168.0.1",
34 VipAddress: "192.168.0.1",
35 SecureVipAddress: "192.168.0.1",
36 HealthCheckUrl: "http://serveregistrar1.acme.org:8080/healthz",
37 StatusPageUrl: "http://serveregistrar1.acme.org:8080/status",
38 HomePageUrl: "http://serveregistrar1.acme.org:8080/",
39 Status: fargo.UP,
40 DataCenterInfo: fargo.DataCenterInfo{Name: fargo.MyOwn},
41 LeaseInfo: fargo.LeaseInfo{RenewalIntervalInSecs: 1},
42 }
43 instanceTest2 = &fargo.Instance{
44 HostName: "serveregistrar2.acme.org",
45 Port: 8080,
46 App: appNameTest,
47 IPAddr: "192.168.0.2",
48 VipAddress: "192.168.0.2",
49 SecureVipAddress: "192.168.0.2",
50 HealthCheckUrl: "http://serveregistrar2.acme.org:8080/healthz",
51 StatusPageUrl: "http://serveregistrar2.acme.org:8080/status",
52 HomePageUrl: "http://serveregistrar2.acme.org:8080/",
53 Status: fargo.UP,
54 DataCenterInfo: fargo.DataCenterInfo{Name: fargo.MyOwn},
55 }
56 )
57
58 var _ fargoConnection = (*testConnection)(nil)
59
60 func (c *testConnection) RegisterInstance(i *fargo.Instance) error {
61 if c.errRegister == nil {
62 for _, instance := range c.instances {
63 if reflect.DeepEqual(*instance, *i) {
64 return errors.New("already registered")
65 }
66 }
67
68 c.instances = append(c.instances, i)
69 }
70 return c.errRegister
71 }
72
73 func (c *testConnection) HeartBeatInstance(i *fargo.Instance) error {
74 return c.errHeartbeat
75 }
76
77 func (c *testConnection) DeregisterInstance(i *fargo.Instance) error {
78 if c.errDeregister == nil {
79 var newInstances []*fargo.Instance
80 for _, instance := range c.instances {
81 if reflect.DeepEqual(*instance, *i) {
82 continue
83 }
84 newInstances = append(newInstances, instance)
85 }
86 if len(newInstances) == len(c.instances) {
87 return errors.New("not registered")
88 }
89
90 c.instances = newInstances
91 }
92 return c.errDeregister
93 }
94
95 func (c *testConnection) ReregisterInstance(ins *fargo.Instance) error {
96 return nil
97 }
98
99 func (c *testConnection) ScheduleAppUpdates(name string, await bool, done <-chan struct{}) <-chan fargo.AppUpdate {
100 updatec := make(chan fargo.AppUpdate, 1)
101 updatec <- fargo.AppUpdate{App: c.application, Err: c.errApplication}
102 return updatec
103 }
104
105 func (c *testConnection) GetApp(name string) (*fargo.Application, error) {
106 return &fargo.Application{Name: appNameTest, Instances: c.instances}, c.errInstances
107 }