https://github.com/api7/etcd-adapter
Embed ETCD into your program in a lightweight manner
https://github.com/api7/etcd-adapter
Last synced: 9 months ago
JSON representation
Embed ETCD into your program in a lightweight manner
- Host: GitHub
- URL: https://github.com/api7/etcd-adapter
- Owner: api7
- License: apache-2.0
- Created: 2021-06-21T05:36:40.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2025-03-13T05:43:51.000Z (11 months ago)
- Last Synced: 2025-04-13T06:25:44.392Z (10 months ago)
- Language: Go
- Homepage: https://pkg.go.dev/github.com/api7/etcd-adapter
- Size: 159 KB
- Stars: 80
- Watchers: 6
- Forks: 24
- Open Issues: 19
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
ETCD Adapter
============
ETCD Adapter mimics the [ETCD V3 APIs](https://etcd.io/docs/v3.3/rfc/) best effort. It incorporates the [kine](https://github.com/k3s-io/kine) as the
Server side implementation, and it develops a totally in-memory watchable backend.
**Not all features in ETCD V3 APIs supported**, this is designed for [Apache APISIX](https://apisix.apache.org), so it's inherently not a generic solution.
How to use it
-------------
It's easy to create an etcd adapter instance. The use of this instance contains two parts, the first thing is you should prepare a network listener and let it run. ETCD adapter
launches a gRPC service (with a built-in [gRPC Gateway](https://github.com/grpc-ecosystem/grpc-gateway), so that HTTP Restful requests can also be handled), you can try to access this
service with the [etcdctl](https://github.com/etcd-io/etcd/tree/main/etcdctl) tool.
The another thing is you should feed some events to this instance, so that data changes can be applied to the instance and ultimately it affects the end-user of this gRPC service.
```go
package main
import (
"context"
"fmt"
"math/rand"
"net"
"time"
adapter "github.com/api7/etcd-adapter"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func main() {
a := adapter.NewEtcdAdapter(nil)
ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Hour)
defer cancel()
go produceEvents(ctx, a)
ln, err := net.Listen("tcp", "127.0.0.1:12379")
if err != nil {
panic(err)
}
go func() {
if err := a.Serve(context.Background(), ln); err != nil {
panic(err)
}
}()
<-ctx.Done()
if err := a.Shutdown(context.TODO()); err != nil {
panic(err)
}
}
func produceEvents(ctx context.Context, a adapter.Adapter) {
ticker := time.NewTicker(time.Second)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
break
}
event := &adapter.Event{
Type: adapter.EventType(rand.Intn(3) + 1),
Key: fmt.Sprintf("/key/part/%d", rand.Int()),
}
if event.Type != adapter.EventDelete {
event.Value = []byte(fmt.Sprintf("value-%d", rand.Int()))
}
a.EventCh() <- []*adapter.Event{event}
}
}
```
The above example shows a simple usage about the etcd adapter.
**Note, get keys by prefix constrained strictly as the key format has to be path-like**, for instance, keys can be `/apisix/routes/1`, `apisix/upstreams/2`, and you can get them with
the prefix `/apisix`, or `/apisix/routes`, `/apisix/upstreams` perspective.