Implementation and tests for certmagic.Storage interface
This commit is contained in:
parent
a6e95d389f
commit
7d2afa34a0
@ -2,11 +2,16 @@ package certmagic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-acme/lego/v3/providers/dns/cloudflare"
|
"github.com/go-acme/lego/v3/providers/dns/cloudflare"
|
||||||
"github.com/mholt/certmagic"
|
"github.com/mholt/certmagic"
|
||||||
"github.com/micro/go-micro/api/server/acme"
|
"github.com/micro/go-micro/api/server/acme"
|
||||||
|
"github.com/micro/go-micro/config/options"
|
||||||
|
cloudflarestorage "github.com/micro/go-micro/store/cloudflare"
|
||||||
"github.com/micro/go-micro/sync/lock/memory"
|
"github.com/micro/go-micro/sync/lock/memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,13 +48,140 @@ func TestCertMagic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestStorageImplementation(t *testing.T) {
|
func TestStorageImplementation(t *testing.T) {
|
||||||
var s certmagic.Storage
|
apiToken, accountID := os.Getenv("CF_API_TOKEN"), os.Getenv("CF_ACCOUNT_ID")
|
||||||
s = &storage{
|
kvID := os.Getenv("KV_NAMESPACE_ID")
|
||||||
lock: memory.NewLock(),
|
if len(apiToken) == 0 || len(accountID) == 0 || len(kvID) == 0 {
|
||||||
|
t.Skip("No Cloudflare API keys available, skipping test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var s certmagic.Storage
|
||||||
|
st, err := cloudflarestorage.New(
|
||||||
|
options.WithValue("CF_API_TOKEN", apiToken),
|
||||||
|
options.WithValue("CF_ACCOUNT_ID", accountID),
|
||||||
|
options.WithValue("KV_NAMESPACE_ID", kvID),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Couldn't initialise cloudflare storage: %s\n", err.Error())
|
||||||
|
}
|
||||||
|
s = &storage{
|
||||||
|
lock: memory.NewLock(),
|
||||||
|
store: st,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Lock
|
||||||
if err := s.Lock("test"); err != nil {
|
if err := s.Lock("test"); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
s.Unlock("test")
|
|
||||||
|
// Test Unlock
|
||||||
|
if err := s.Unlock("test"); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test data
|
||||||
|
testdata := []struct {
|
||||||
|
key string
|
||||||
|
value []byte
|
||||||
|
}{
|
||||||
|
{key: "/foo/a", value: []byte("lorem")},
|
||||||
|
{key: "/foo/b", value: []byte("ipsum")},
|
||||||
|
{key: "/foo/c", value: []byte("dolor")},
|
||||||
|
{key: "/foo/d", value: []byte("sit")},
|
||||||
|
{key: "/bar/a", value: []byte("amet")},
|
||||||
|
{key: "/bar/b", value: []byte("consectetur")},
|
||||||
|
{key: "/bar/c", value: []byte("adipiscing")},
|
||||||
|
{key: "/bar/d", value: []byte("elit")},
|
||||||
|
{key: "/foo/bar/a", value: []byte("sed")},
|
||||||
|
{key: "/foo/bar/b", value: []byte("do")},
|
||||||
|
{key: "/foo/bar/c", value: []byte("eiusmod")},
|
||||||
|
{key: "/foo/bar/d", value: []byte("tempor")},
|
||||||
|
{key: "/foo/bar/baz/a", value: []byte("incididunt")},
|
||||||
|
{key: "/foo/bar/baz/b", value: []byte("ut")},
|
||||||
|
{key: "/foo/bar/baz/c", value: []byte("labore")},
|
||||||
|
{key: "/foo/bar/baz/d", value: []byte("et")},
|
||||||
|
// a duplicate just in case there's any edge cases
|
||||||
|
{key: "/foo/a", value: []byte("lorem")},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Store
|
||||||
|
for _, d := range testdata {
|
||||||
|
if err := s.Store(d.key, d.value); err != nil {
|
||||||
|
t.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Load
|
||||||
|
for _, d := range testdata {
|
||||||
|
if value, err := s.Load(d.key); err != nil {
|
||||||
|
t.Error(err.Error())
|
||||||
|
} else {
|
||||||
|
if !reflect.DeepEqual(value, d.value) {
|
||||||
|
t.Errorf("Load %s: expected %v, got %v", d.key, d.value, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Exists
|
||||||
|
for _, d := range testdata {
|
||||||
|
if !s.Exists(d.key) {
|
||||||
|
t.Errorf("%s should exist, but doesn't\n", d.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test List
|
||||||
|
if list, err := s.List("/", true); err != nil {
|
||||||
|
t.Error(err.Error())
|
||||||
|
} else {
|
||||||
|
var expected []string
|
||||||
|
for i, d := range testdata {
|
||||||
|
if i != len(testdata)-1 {
|
||||||
|
// Don't store the intentionally duplicated key
|
||||||
|
expected = append(expected, d.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(expected)
|
||||||
|
sort.Strings(list)
|
||||||
|
if !reflect.DeepEqual(expected, list) {
|
||||||
|
t.Errorf("List: Expected %v, got %v\n", expected, list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if list, err := s.List("/foo", false); err != nil {
|
||||||
|
t.Error(err.Error())
|
||||||
|
} else {
|
||||||
|
sort.Strings(list)
|
||||||
|
expected := []string{"/foo/a", "/foo/b", "/foo/bar", "/foo/c", "/foo/d"}
|
||||||
|
if !reflect.DeepEqual(expected, list) {
|
||||||
|
t.Errorf("List: expected %s, got %s\n", expected, list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Stat
|
||||||
|
for _, d := range testdata {
|
||||||
|
info, err := s.Stat(d.key)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err.Error())
|
||||||
|
} else {
|
||||||
|
if info.Key != d.key {
|
||||||
|
t.Errorf("Stat().Key: expected %s, got %s\n", d.key, info.Key)
|
||||||
|
}
|
||||||
|
if info.Size != int64(len(d.value)) {
|
||||||
|
t.Errorf("Stat().Size: expected %d, got %d\n", len(d.value), info.Size)
|
||||||
|
}
|
||||||
|
if time.Since(info.Modified) > time.Minute {
|
||||||
|
t.Errorf("Stat().Modified: expected time since last modified to be < 1 minute, got %v\n", time.Since(info.Modified))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Delete
|
||||||
|
for _, d := range testdata {
|
||||||
|
if err := s.Delete(d.key); err != nil {
|
||||||
|
t.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New interface doesn't return an error, so call it in case any log.Fatal
|
||||||
|
// happens
|
||||||
New(acme.Cache(s))
|
New(acme.Cache(s))
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,12 @@ import (
|
|||||||
"github.com/micro/go-micro/sync/lock"
|
"github.com/micro/go-micro/sync/lock"
|
||||||
)
|
)
|
||||||
|
|
||||||
// file represents a "file" that will be stored in store.Store - the contents and last modified time
|
// File represents a "File" that will be stored in store.Store - the contents and last modified time
|
||||||
type file struct {
|
type File struct {
|
||||||
// last modified time
|
// last modified time
|
||||||
lastModified time.Time
|
LastModified time.Time
|
||||||
// contents
|
// Contents
|
||||||
contents []byte
|
Contents []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage is an implementation of certmagic.Storage using micro's sync.Map and store.Store interfaces.
|
// storage is an implementation of certmagic.Storage using micro's sync.Map and store.Store interfaces.
|
||||||
@ -38,9 +38,9 @@ func (s *storage) Unlock(key string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) Store(key string, value []byte) error {
|
func (s *storage) Store(key string, value []byte) error {
|
||||||
f := file{
|
f := File{
|
||||||
lastModified: time.Now(),
|
LastModified: time.Now(),
|
||||||
contents: value,
|
Contents: value,
|
||||||
}
|
}
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
e := gob.NewEncoder(buf)
|
e := gob.NewEncoder(buf)
|
||||||
@ -64,12 +64,12 @@ func (s *storage) Load(key string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
b := bytes.NewBuffer(records[0].Value)
|
b := bytes.NewBuffer(records[0].Value)
|
||||||
d := gob.NewDecoder(b)
|
d := gob.NewDecoder(b)
|
||||||
var f file
|
var f File
|
||||||
err = d.Decode(&f)
|
err = d.Decode(&f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return f.contents, nil
|
return f.Contents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) Delete(key string) error {
|
func (s *storage) Delete(key string) error {
|
||||||
@ -120,15 +120,15 @@ func (s *storage) Stat(key string) (certmagic.KeyInfo, error) {
|
|||||||
}
|
}
|
||||||
b := bytes.NewBuffer(records[0].Value)
|
b := bytes.NewBuffer(records[0].Value)
|
||||||
d := gob.NewDecoder(b)
|
d := gob.NewDecoder(b)
|
||||||
var f file
|
var f File
|
||||||
err = d.Decode(&f)
|
err = d.Decode(&f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return certmagic.KeyInfo{}, err
|
return certmagic.KeyInfo{}, err
|
||||||
}
|
}
|
||||||
return certmagic.KeyInfo{
|
return certmagic.KeyInfo{
|
||||||
Key: key,
|
Key: key,
|
||||||
Modified: f.lastModified,
|
Modified: f.LastModified,
|
||||||
Size: int64(len(f.contents)),
|
Size: int64(len(f.Contents)),
|
||||||
IsTerminal: false,
|
IsTerminal: false,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user