Skip to content

Commit

Permalink
feat: add fake client
Browse files Browse the repository at this point in the history
Signed-off-by: Artashes Balabekyan <balabekyanartashes@gmail.com>
  • Loading branch information
artashesbalabekyan committed Jul 2, 2023
1 parent c93e478 commit 9781260
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 39 deletions.
5 changes: 5 additions & 0 deletions barbican.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import (
"context"

"github.com/artashesbalabekyan/barbican-sdk-go/client"
"github.com/artashesbalabekyan/barbican-sdk-go/fake"
"github.com/artashesbalabekyan/barbican-sdk-go/xhttp"
)

func NewConnection(ctx context.Context, config *xhttp.Config) (client.Conn, error) {
return client.New(ctx, config)
}

func NewFakeConnection(ctx context.Context, fakeData map[string][]byte) (client.Conn, error) {
return fake.New(ctx, fakeData)
}
44 changes: 8 additions & 36 deletions client/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,13 @@ package client

import "context"

type Iterator struct {
ch <-chan string
ctx context.Context
cancel context.CancelCauseFunc
type Iterator interface {
Next() (string, bool)
Close() error
}

// Next moves the iterator to the next key, if any.
// This key is available until Next is called again.
//
// It returns true if and only if there is a new key
// available. If there are no more keys or an error
// has been encountered, Next returns false.
func (i *Iterator) Next() (string, bool) {
select {
case v, ok := <-i.ch:
return v, ok
case <-i.ctx.Done():
return "", false
}
}

// Err returns the first error, if any, encountered
// while iterating over the set of keys.
func (i *Iterator) Close() error {
// i.cancel(context.Canceled)
return context.Cause(i.ctx)
}

type namePayload struct {
name string
payload []byte
}

type IteratorWithPayload struct {
ch <-chan namePayload
type ListIterator struct {
ch <-chan string
ctx context.Context
cancel context.CancelCauseFunc
}
Expand All @@ -47,18 +19,18 @@ type IteratorWithPayload struct {
// It returns true if and only if there is a new key
// available. If there are no more keys or an error
// has been encountered, Next returns false.
func (i *IteratorWithPayload) Next() (namePayload, bool) {
func (i *ListIterator) Next() (string, bool) {
select {
case v, ok := <-i.ch:
return v, ok
case <-i.ctx.Done():
return namePayload{}, false
return "", false
}
}

// Err returns the first error, if any, encountered
// while iterating over the set of keys.
func (i *IteratorWithPayload) Close() error {
func (i *ListIterator) Close() error {
// i.cancel(context.Canceled)
return context.Cause(i.ctx)
}
4 changes: 2 additions & 2 deletions client/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (c *Client) DeleteSecret(ctx context.Context, name string) error {
// concurrent changes to the Barbican - i.e.
// creates or deletec. Further, it does not provide any
// ordering guaranteec.
func (c *Client) ListSecrets(ctx context.Context) (*Iterator, error) {
func (c *Client) ListSecrets(ctx context.Context) (Iterator, error) {
var cancel context.CancelCauseFunc
ctx, cancel = context.WithCancelCause(ctx)
values := make(chan string, 10)
Expand Down Expand Up @@ -149,7 +149,7 @@ func (c *Client) ListSecrets(ctx context.Context) (*Iterator, error) {
}
}
}()
return &Iterator{
return &ListIterator{
ch: values,
ctx: ctx,
cancel: cancel,
Expand Down
2 changes: 1 addition & 1 deletion client/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type Conn interface {
GetSecret(ctx context.Context, name string) (*BarbicanSecret, error)
GetSecretWithPayload(ctx context.Context, name string) (*BarbicanSecretWithPayload, error)
DeleteSecret(ctx context.Context, name string) error
ListSecrets(ctx context.Context) (*Iterator, error)
ListSecrets(ctx context.Context) (Iterator, error)
}

type Client struct {
Expand Down
17 changes: 17 additions & 0 deletions fake/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fake

import (
"context"

"github.com/artashesbalabekyan/barbican-sdk-go/client"
)

func New(ctx context.Context, fakeData map[string][]byte) (client.Conn, error) {
return newConnection(ctx, fakeData)
}

func newConnection(ctx context.Context, fakeData map[string][]byte) (client.Conn, error) {
return &Client{
fakeData: NewFakeData(fakeData),
}, nil
}
71 changes: 71 additions & 0 deletions fake/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package fake

import (
"time"

"github.com/artashesbalabekyan/barbican-sdk-go/client"
)

const (
timeFormat = "2006-01-02T15:04:05"
)

func newCreationTime() string {
return time.Now().Format(timeFormat)
}

func NewFakeData(d map[string][]byte) *FakeData {
f := &FakeData{
data: make(map[string]client.BarbicanSecretWithPayload),
}
for name, payload := range d {
f.Set(name, NewSecret(name, payload))
}
return f
}

func NewSecret(name string, payload []byte) client.BarbicanSecretWithPayload {
return client.BarbicanSecretWithPayload{
Secret: client.BarbicanSecret{
Algorithm: "aes",
BitLength: 256,
ContentTypes: map[string]string{"default": "application/octet-stream"},
Created: newCreationTime(),
Mode: "cbc",
Name: name,
SecretType: "opaque",
Status: "ACTIVE",
Updated: newCreationTime(),
},
Payload: payload,
}
}

func (f *FakeData) Set(name string, secret client.BarbicanSecretWithPayload) {
f.Lock()
f.data[name] = secret
f.Unlock()
}

func (f *FakeData) Get(name string) (secret client.BarbicanSecretWithPayload, exist bool) {
f.RLock()
secret, exist = f.data[name]
f.RUnlock()
return
}

func (f *FakeData) Delete(name string) {
f.Lock()
delete(f.data, name)
f.Unlock()
}

func (f *FakeData) List() []client.BarbicanSecret {
f.RLock()
list := []client.BarbicanSecret{}
for _, secret := range f.data {
list = append(list, secret.Secret)
}
f.RUnlock()
return list
}
31 changes: 31 additions & 0 deletions fake/iterator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package fake

import "context"

type Iterator struct {
ch <-chan string
ctx context.Context
cancel context.CancelCauseFunc
}

// Next moves the iterator to the next key, if any.
// This key is available until Next is called again.
//
// It returns true if and only if there is a new key
// available. If there are no more keys or an error
// has been encountered, Next returns false.
func (i *Iterator) Next() (string, bool) {
select {
case v, ok := <-i.ch:
return v, ok
case <-i.ctx.Done():
return "", false
}
}

// Err returns the first error, if any, encountered
// while iterating over the set of keys.
func (i *Iterator) Close() error {
// i.cancel(context.Canceled)
return context.Cause(i.ctx)
}
73 changes: 73 additions & 0 deletions fake/secrets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package fake

import (
"context"
"fmt"

"github.com/artashesbalabekyan/barbican-sdk-go/client"
"github.com/artashesbalabekyan/barbican-sdk-go/xerror"
)

// Create stores the given key in Barbican if and only
// if no entry with the given name existc.
//
// If no such entry exists, Create returns ErrKeyExistc.
func (c *Client) Create(ctx context.Context, name string, value []byte) error {
if len(value) == 0 {
return fmt.Errorf("couldn't create. Provided object does not match schema 'Secret': If 'payload' specified, must be non empty. Invalid property: 'payload'")
}
secret := NewSecret(name, value)
c.fakeData.Set(name, secret)
return nil
}

func (c *Client) GetSecret(ctx context.Context, name string) (*client.BarbicanSecret, error) {
s, ok := c.fakeData.Get(name)
if !ok {
return nil, xerror.ErrKeyNotFound
}

return &s.Secret, nil
}

func (c *Client) GetSecretWithPayload(ctx context.Context, name string) (*client.BarbicanSecretWithPayload, error) {
s, ok := c.fakeData.Get(name)
if !ok {
return nil, xerror.ErrKeyNotFound
}
return &s, nil
}

func (c *Client) DeleteSecret(ctx context.Context, name string) error {
c.fakeData.Delete(name)
return nil
}

// List returns a new Iterator over the Barbican.
//
// The returned iterator may or may not reflect any
// concurrent changes to the Barbican - i.e.
// creates or deletec. Further, it does not provide any
// ordering guaranteec.
func (c *Client) ListSecrets(ctx context.Context) (client.Iterator, error) {
var cancel context.CancelCauseFunc
ctx, cancel = context.WithCancelCause(ctx)
values := make(chan string, 10)

go func() {
defer close(values)
keys := c.fakeData.List()
for _, k := range keys {
select {
case values <- k.Name:
case <-ctx.Done():
return
}
}
}()
return &Iterator{
ch: values,
ctx: ctx,
cancel: cancel,
}, nil
}
16 changes: 16 additions & 0 deletions fake/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fake

import (
"sync"

"github.com/artashesbalabekyan/barbican-sdk-go/client"
)

type Client struct {
fakeData *FakeData
}

type FakeData struct {
data map[string]client.BarbicanSecretWithPayload
sync.RWMutex
}

0 comments on commit 9781260

Please sign in to comment.