12 "github.com/go-kit/kit/endpoint"
13 "github.com/go-kit/kit/log"
14 "github.com/go-kit/kit/sd"
17 // Package sd/etcd provides a wrapper around the etcd key/value store. This
18 // example assumes the user has an instance of etcd installed and running
19 // locally on port 2379.
20 func TestIntegration(t *testing.T) {
21 addr := os.Getenv("ETCD_ADDR")
23 t.Skip("ETCD_ADDR not set; skipping integration test")
27 prefix = "/services/foosvc/" // known at compile time
28 instance = "1.2.3.4:8080" // taken from runtime or platform, somehow
29 key = prefix + instance
30 value = "http://" + instance // based on our transport
33 client, err := NewClient(context.Background(), []string{addr}, ClientOptions{
34 DialTimeout: 2 * time.Second,
35 DialKeepAlive: 2 * time.Second,
36 HeaderTimeoutPerRequest: 2 * time.Second,
39 t.Fatalf("NewClient(%q): %v", addr, err)
42 // Verify test data is initially empty.
43 entries, err := client.GetEntries(key)
45 t.Fatalf("GetEntries(%q): expected error, got none", key)
47 t.Logf("GetEntries(%q): %v (OK)", key, err)
49 // Instantiate a new Registrar, passing in test data.
50 registrar := NewRegistrar(client, Service{
53 }, log.With(log.NewLogfmtLogger(os.Stderr), "component", "registrar"))
55 // Register our instance.
59 // Retrieve entries from etcd manually.
60 entries, err = client.GetEntries(key)
62 t.Fatalf("client.GetEntries(%q): %v", key, err)
64 if want, have := 1, len(entries); want != have {
65 t.Fatalf("client.GetEntries(%q): want %d, have %d", key, want, have)
67 if want, have := value, entries[0]; want != have {
68 t.Fatalf("want %q, have %q", want, have)
71 instancer, err := NewInstancer(
74 log.With(log.NewLogfmtLogger(os.Stderr), "component", "instancer"),
77 t.Fatalf("NewInstancer: %v", err)
79 endpointer := sd.NewEndpointer(
81 func(string) (endpoint.Endpoint, io.Closer, error) { return endpoint.Nop, nil, nil },
82 log.With(log.NewLogfmtLogger(os.Stderr), "component", "instancer"),
84 t.Logf("Constructed Endpointer OK")
86 if !within(time.Second, func() bool {
87 endpoints, err := endpointer.Endpoints()
88 return err == nil && len(endpoints) == 1
90 t.Fatalf("Endpointer didn't see Register in time")
92 t.Logf("Endpointer saw Register OK")
94 // Deregister first instance of test data.
95 registrar.Deregister()
96 t.Logf("Deregistered")
98 // Check it was deregistered.
99 if !within(time.Second, func() bool {
100 endpoints, err := endpointer.Endpoints()
101 t.Logf("Checking Deregister: len(endpoints) = %d, err = %v", len(endpoints), err)
102 return err == nil && len(endpoints) == 0
104 t.Fatalf("Endpointer didn't see Deregister in time")
107 // Verify test data no longer exists in etcd.
108 _, err = client.GetEntries(key)
110 t.Fatalf("GetEntries(%q): expected error, got none", key)
112 t.Logf("GetEntries(%q): %v (OK)", key, err)
115 func within(d time.Duration, f func() bool) bool {
116 deadline := time.Now().Add(d)
117 for time.Now().Before(deadline) {