From 43118656b3d542ae7087d03b4399678834325381 Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Tue, 16 Jan 2018 17:37:41 +0100 Subject: [PATCH 1/4] Consul backend --- backend/consul/consul.go | 39 +++++++++++++++++++++++++++++++++++ backend/consul/consul_test.go | 32 ++++++++++++++++++++++++++++ glide.yaml | 4 ++++ 3 files changed, 75 insertions(+) create mode 100644 backend/consul/consul.go create mode 100644 backend/consul/consul_test.go diff --git a/backend/consul/consul.go b/backend/consul/consul.go new file mode 100644 index 0000000..eead2a1 --- /dev/null +++ b/backend/consul/consul.go @@ -0,0 +1,39 @@ +package consul + +import ( + "context" + "path" + + "github.com/hashicorp/consul/api" + "github.com/heetch/confita/backend" +) + +// Backend loads keys from Consul. +type Backend struct { + client *api.Client + prefix string +} + +// NewBackend creates a configuration loader that loads from Consul. +func NewBackend(client *api.Client, prefix string) *Backend { + return &Backend{ + client: client, + prefix: prefix, + } +} + +// Get loads the given key from Consul. +func (b *Backend) Get(ctx context.Context, key string) ([]byte, error) { + var opt api.QueryOptions + + kv, _, err := b.client.KV().Get(path.Join(b.prefix, key), opt.WithContext(ctx)) + if err != nil { + return nil, err + } + + if kv == nil { + return nil, backend.ErrNotFound + } + + return kv.Value, nil +} diff --git a/backend/consul/consul_test.go b/backend/consul/consul_test.go new file mode 100644 index 0000000..9d8633f --- /dev/null +++ b/backend/consul/consul_test.go @@ -0,0 +1,32 @@ +package consul + +import ( + "context" + "testing" + + "github.com/hashicorp/consul/api" + "github.com/heetch/confita/backend" + "github.com/stretchr/testify/require" +) + +func TestConsulBackend(t *testing.T) { + client, err := api.NewClient(api.DefaultConfig()) + require.NoError(t, err) + + b := NewBackend(client, "prefix") + + t.Run("NotFound", func(t *testing.T) { + _, err = b.Get(context.Background(), "something that doesn't exist") + require.Equal(t, backend.ErrNotFound, err) + }) + + t.Run("OK", func(t *testing.T) { + _, err = client.KV().Put(&api.KVPair{Key: "prefix/key1", Value: []byte("value")}, nil) + require.NoError(t, err) + defer client.KV().Delete("prefix/key1", nil) + + val, err := b.Get(context.Background(), "key1") + require.NoError(t, err) + require.Equal(t, []byte("value"), val) + }) +} diff --git a/glide.yaml b/glide.yaml index bc0fe95..290d844 100644 --- a/glide.yaml +++ b/glide.yaml @@ -4,6 +4,10 @@ import: version: ^3.0.0 subpackages: - clientv3 +- package: github.com/hashicorp/consul + version: ^1.0.0 + subpackages: + - api testImport: - package: github.com/stretchr/testify version: ^1.1.4 From d2a8003b48b68d05f9a8a7aa3d342eec31c1dc25 Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Tue, 16 Jan 2018 17:38:38 +0100 Subject: [PATCH 2/4] Adding Consul to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b9894d4..6b4d1c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ before_install: - tar -vxz -C $GOPATH/bin --strip=1 -f glide-v0.13.1-linux-amd64.tar.gz - export PATH="$GOPATH/bin:$PATH" - docker run -d -p 2379:2379 quay.io/coreos/etcd /usr/local/bin/etcd -advertise-client-urls http://0.0.0.0:2379 -listen-client-urls http://0.0.0.0:2379 + - docker run -d -p 8500:8500 --name consul consul install: glide install From 4e95f98a909422b565fdf4b77b754b5b5f81c768 Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Tue, 16 Jan 2018 17:52:38 +0100 Subject: [PATCH 3/4] Testing with canceled context --- backend/consul/consul_test.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/consul/consul_test.go b/backend/consul/consul_test.go index 9d8633f..5f43b4d 100644 --- a/backend/consul/consul_test.go +++ b/backend/consul/consul_test.go @@ -10,10 +10,13 @@ import ( ) func TestConsulBackend(t *testing.T) { + prefix := "confita-tests" + client, err := api.NewClient(api.DefaultConfig()) require.NoError(t, err) + defer client.KV().DeleteTree(prefix, nil) - b := NewBackend(client, "prefix") + b := NewBackend(client, prefix) t.Run("NotFound", func(t *testing.T) { _, err = b.Get(context.Background(), "something that doesn't exist") @@ -21,12 +24,21 @@ func TestConsulBackend(t *testing.T) { }) t.Run("OK", func(t *testing.T) { - _, err = client.KV().Put(&api.KVPair{Key: "prefix/key1", Value: []byte("value")}, nil) + _, err = client.KV().Put(&api.KVPair{Key: prefix + "/key1", Value: []byte("value")}, nil) require.NoError(t, err) - defer client.KV().Delete("prefix/key1", nil) val, err := b.Get(context.Background(), "key1") require.NoError(t, err) require.Equal(t, []byte("value"), val) }) + + t.Run("Canceled", func(t *testing.T) { + _, err = client.KV().Put(&api.KVPair{Key: prefix + "/key2", Value: []byte("value")}, nil) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, err = b.Get(ctx, "key2") + require.Error(t, err) + }) } From ddbd21873c7e8e0133f3920d599c87ebb854510e Mon Sep 17 00:00:00 2001 From: Asdine El Hrychy Date: Tue, 16 Jan 2018 17:53:10 +0100 Subject: [PATCH 4/4] Adding Consul to README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 40751da..35d3304 100644 --- a/README.md +++ b/README.md @@ -71,12 +71,13 @@ loader := confita.NewLoader() ``` By default, a Confita loader loads all the keys from the environment. -A loader can take other configured backends as parameters. For now, only [etcd](https://github.com/coreos/etcd) is supported. +A loader can take other configured backends as parameters. For now, [etcd](https://github.com/coreos/etcd) and [Consul](https://www.consul.io/) are supported. ```go loader := confita.NewLoader( env.NewBackend(), etcd.NewBackend(etcdClientv3, "namespace"), + consul.NewBackend(consulClient, "namespace"), ) ```