1package etcdv3
2
3import (
4	"context"
5	"io"
6	"time"
7
8	"github.com/go-kit/kit/endpoint"
9	"github.com/go-kit/kit/log"
10	"github.com/go-kit/kit/sd"
11	"github.com/go-kit/kit/sd/lb"
12)
13
14func Example() {
15	// Let's say this is a service that means to register itself.
16	// First, we will set up some context.
17	var (
18		etcdServer = "10.0.0.1:2379"      // in the change from v2 to v3, the schema is no longer necessary if connecting directly to an etcd v3 instance
19		prefix     = "/services/foosvc/"  // known at compile time
20		instance   = "1.2.3.4:8080"       // taken from runtime or platform, somehow
21		key        = prefix + instance    // should be globally unique
22		value      = "http://" + instance // based on our transport
23		ctx        = context.Background()
24	)
25
26	options := ClientOptions{
27		// Path to trusted ca file
28		CACert: "",
29
30		// Path to certificate
31		Cert: "",
32
33		// Path to private key
34		Key: "",
35
36		// Username if required
37		Username: "",
38
39		// Password if required
40		Password: "",
41
42		// If DialTimeout is 0, it defaults to 3s
43		DialTimeout: time.Second * 3,
44
45		// If DialKeepAlive is 0, it defaults to 3s
46		DialKeepAlive: time.Second * 3,
47	}
48
49	// Build the client.
50	client, err := NewClient(ctx, []string{etcdServer}, options)
51	if err != nil {
52		panic(err)
53	}
54
55	// Build the registrar.
56	registrar := NewRegistrar(client, Service{
57		Key:   key,
58		Value: value,
59	}, log.NewNopLogger())
60
61	// Register our instance.
62	registrar.Register()
63
64	// At the end of our service lifecycle, for example at the end of func main,
65	// we should make sure to deregister ourselves. This is important! Don't
66	// accidentally skip this step by invoking a log.Fatal or os.Exit in the
67	// interim, which bypasses the defer stack.
68	defer registrar.Deregister()
69
70	// It's likely that we'll also want to connect to other services and call
71	// their methods. We can build an Instancer to listen for changes from etcd,
72	// create Endpointer, wrap it with a load-balancer to pick a single
73	// endpoint, and finally wrap it with a retry strategy to get something that
74	// can be used as an endpoint directly.
75	barPrefix := "/services/barsvc"
76	logger := log.NewNopLogger()
77	instancer, err := NewInstancer(client, barPrefix, logger)
78	if err != nil {
79		panic(err)
80	}
81	endpointer := sd.NewEndpointer(instancer, barFactory, logger)
82	balancer := lb.NewRoundRobin(endpointer)
83	retry := lb.Retry(3, 3*time.Second, balancer)
84
85	// And now retry can be used like any other endpoint.
86	req := struct{}{}
87	if _, err = retry(ctx, req); err != nil {
88		panic(err)
89	}
90}
91
92func barFactory(string) (endpoint.Endpoint, io.Closer, error) { return endpoint.Nop, nil, nil }
93