physical: Adding Consul backend
This commit is contained in:
parent
3250bfad0a
commit
1d839d033c
|
@ -1,14 +1,102 @@
|
|||
package physical
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
// ConsulBackend is a physical backend that stores data at specific
|
||||
// prefix within Consul. It is used for most production situations as
|
||||
// it allows Vault to run on multiple machines in a highly-available manner.
|
||||
type ConsulBackend struct {
|
||||
path string
|
||||
client *api.Client
|
||||
kv *api.KV
|
||||
}
|
||||
|
||||
// newConsulBackend constructs a Consul backend using the given API client
|
||||
// and the prefix in the KV store.
|
||||
func newConsulBackend(conf map[string]string) (Backend, error) {
|
||||
// TODO
|
||||
// Get the path in Consul
|
||||
path, ok := conf["path"]
|
||||
if !ok || path == "" || path == "/" {
|
||||
return nil, fmt.Errorf("'path' must be set")
|
||||
}
|
||||
if !strings.HasSuffix(path, "/") {
|
||||
path += "/"
|
||||
}
|
||||
|
||||
// Configure the client
|
||||
consulConf := api.DefaultConfig()
|
||||
if addr, ok := conf["address"]; ok {
|
||||
consulConf.Address = addr
|
||||
}
|
||||
if scheme, ok := conf["scheme"]; ok {
|
||||
consulConf.Scheme = scheme
|
||||
}
|
||||
if dc, ok := conf["datacenter"]; ok {
|
||||
consulConf.Datacenter = dc
|
||||
}
|
||||
if token, ok := conf["token"]; ok {
|
||||
consulConf.Token = token
|
||||
}
|
||||
client, err := api.NewClient(consulConf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("client setup failed: %v", err)
|
||||
}
|
||||
|
||||
// Setup the backend
|
||||
c := &ConsulBackend{
|
||||
path: path,
|
||||
client: client,
|
||||
kv: client.KV(),
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Put is used to insert or update an entry
|
||||
func (c *ConsulBackend) Put(entry *Entry) error {
|
||||
pair := &api.KVPair{
|
||||
Key: c.path + entry.Key,
|
||||
Value: entry.Value,
|
||||
}
|
||||
_, err := c.kv.Put(pair, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Get is used to fetch an entry
|
||||
func (c *ConsulBackend) Get(key string) (*Entry, error) {
|
||||
pair, _, err := c.kv.Get(c.path+key, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pair == nil {
|
||||
return nil, nil
|
||||
}
|
||||
ent := &Entry{
|
||||
Key: key,
|
||||
Value: pair.Value,
|
||||
}
|
||||
return ent, nil
|
||||
}
|
||||
|
||||
// Delete is used to permanently delete an entry
|
||||
func (c *ConsulBackend) Delete(key string) error {
|
||||
_, err := c.kv.Delete(c.path+key, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// List is used ot list all the keys under a given
|
||||
// prefix, up to the next prefix.
|
||||
func (c *ConsulBackend) List(prefix string) ([]string, error) {
|
||||
scan := c.path + prefix
|
||||
out, _, err := c.kv.Keys(scan, "/", nil)
|
||||
for idx, val := range out {
|
||||
out[idx] = strings.TrimPrefix(val, scan)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package physical
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
)
|
||||
|
||||
func TestConsulBackend(t *testing.T) {
|
||||
addr := os.Getenv("CONSUL_ADDR")
|
||||
if addr == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = addr
|
||||
client, err := api.NewClient(conf)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
randPath := fmt.Sprintf("vault-%d/", time.Now().Unix())
|
||||
defer func() {
|
||||
client.KV().DeleteTree(randPath, nil)
|
||||
}()
|
||||
|
||||
b, err := NewBackend("consul", map[string]string{
|
||||
"address": addr,
|
||||
"path": randPath,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
testBackend(t, b)
|
||||
testBackend_ListPrefix(t, b)
|
||||
}
|
Loading…
Reference in New Issue