From 99358c5d6e4d2924e27876c2afd1606777c806cf Mon Sep 17 00:00:00 2001 From: Keepers <104464746+ryanfkeepers@users.noreply.github.com> Date: Wed, 25 May 2022 09:50:52 -0600 Subject: [PATCH] introduces storage pkg (#25) (#73) * introduces storage pkg (#25) Adds a new package /pkg/storage. Storage is used to communicate storage provider information throughout the corso app. In particular, it allows per-provider data to cross interface boundaries without slicing their details. * use consts for s3 config keys --- src/pkg/storage/s3.go | 32 ++++++++++++++ src/pkg/storage/s3_test.go | 42 ++++++++++++++++++ src/pkg/storage/storage.go | 41 ++++++++++++++++++ src/pkg/storage/storage_test.go | 52 +++++++++++++++++++++++ src/pkg/storage/storageprovider_string.go | 24 +++++++++++ 5 files changed, 191 insertions(+) create mode 100644 src/pkg/storage/s3.go create mode 100644 src/pkg/storage/s3_test.go create mode 100644 src/pkg/storage/storage.go create mode 100644 src/pkg/storage/storage_test.go create mode 100644 src/pkg/storage/storageprovider_string.go diff --git a/src/pkg/storage/s3.go b/src/pkg/storage/s3.go new file mode 100644 index 000000000..b5c4132da --- /dev/null +++ b/src/pkg/storage/s3.go @@ -0,0 +1,32 @@ +package storage + +type S3Config struct { + Bucket string + AccessKey string + SecretKey string +} + +const ( + keyS3Bucket = "s3_bucket" + keyS3AccessKey = "s3_accessKey" + keyS3SecretKey = "s3_secretKey" +) + +func (c S3Config) Config() config { + return config{ + keyS3Bucket: c.Bucket, + keyS3AccessKey: c.AccessKey, + keyS3SecretKey: c.SecretKey, + } +} + +// S3Config retrieves the S3Config details from the Storage config. +func (s Storage) S3Config() S3Config { + c := S3Config{} + if len(s.Config) > 0 { + c.Bucket = s.Config[keyS3Bucket].(string) + c.AccessKey = s.Config[keyS3AccessKey].(string) + c.SecretKey = s.Config[keyS3SecretKey].(string) + } + return c +} diff --git a/src/pkg/storage/s3_test.go b/src/pkg/storage/s3_test.go new file mode 100644 index 000000000..ab58bb223 --- /dev/null +++ b/src/pkg/storage/s3_test.go @@ -0,0 +1,42 @@ +package storage_test + +import ( + "testing" + + "github.com/alcionai/corso/pkg/storage" +) + +func TestS3Config_Config(t *testing.T) { + s3 := storage.S3Config{"bkt", "ak", "sk"} + c := s3.Config() + table := []struct { + key string + expect string + }{ + {"s3_bucket", s3.Bucket}, + {"s3_accessKey", s3.AccessKey}, + {"s3_secretKey", s3.SecretKey}, + } + for _, test := range table { + key := test.key + expect := test.expect + if c[key] != expect { + t.Errorf("expected config key [%s] to hold value [%s], got [%s]", key, expect, c[key]) + } + } +} + +func TestStorage_S3Config(t *testing.T) { + in := storage.S3Config{"bkt", "ak", "sk"} + s := storage.NewStorage(storage.ProviderS3, in) + out := s.S3Config() + if in.Bucket != out.Bucket { + t.Errorf("expected S3Config.Bucket to be [%s], got [%s]", in.Bucket, out.Bucket) + } + if in.AccessKey != out.AccessKey { + t.Errorf("expected S3Config.AccessKey to be [%s], got [%s]", in.AccessKey, out.AccessKey) + } + if in.SecretKey != out.SecretKey { + t.Errorf("expected S3Config.SecretKey to be [%s], got [%s]", in.SecretKey, out.SecretKey) + } +} diff --git a/src/pkg/storage/storage.go b/src/pkg/storage/storage.go new file mode 100644 index 000000000..40cdd2802 --- /dev/null +++ b/src/pkg/storage/storage.go @@ -0,0 +1,41 @@ +package storage + +type storageProvider int + +//go:generate stringer -type=storageProvider -linecomment +const ( + ProviderUnknown storageProvider = iota // Unknown Provider + ProviderS3 // S3 +) + +type ( + config map[string]any + configurer interface { + Config() config + } +) + +// Storage defines a storage provider, along with any configuration +// requried to set up or communicate with that provider. +type Storage struct { + Provider storageProvider + Config config +} + +// NewStorage aggregates all the supplied configurations into a single configuration. +func NewStorage(p storageProvider, cfgs ...configurer) Storage { + return Storage{ + Provider: p, + Config: unionConfigs(cfgs...), + } +} + +func unionConfigs(cfgs ...configurer) config { + c := config{} + for _, cfg := range cfgs { + for k, v := range cfg.Config() { + c[k] = v + } + } + return c +} diff --git a/src/pkg/storage/storage_test.go b/src/pkg/storage/storage_test.go new file mode 100644 index 000000000..93ca464c4 --- /dev/null +++ b/src/pkg/storage/storage_test.go @@ -0,0 +1,52 @@ +package storage + +import ( + "testing" +) + +type testConfig struct { + expect string +} + +func (c testConfig) Config() config { + return config{"expect": c.expect} +} + +func TestNewStorage(t *testing.T) { + table := []struct { + p storageProvider + c testConfig + }{ + {ProviderUnknown, testConfig{"unknown"}}, + {ProviderS3, testConfig{"s3"}}, + } + for _, test := range table { + s := NewStorage(test.p, test.c) + if s.Provider != test.p { + t.Errorf("expected storage provider [%s], got [%s]", test.p, s.Provider) + } + if s.Config["expect"] != test.c.expect { + t.Errorf("expected storage config [%s], got [%s]", test.c.expect, s.Config["expect"]) + } + } +} + +type fooConfig struct { + foo string +} + +func (c fooConfig) Config() config { + return config{"foo": c.foo} +} + +func TestUnionConfigs(t *testing.T) { + te := testConfig{"test"} + f := fooConfig{"foo"} + cs := unionConfigs(te, f) + if cs["expect"] != te.expect { + t.Errorf("expected unioned config to have value [%s] at key [expect], got [%s]", te.expect, cs["expect"]) + } + if cs["foo"] != f.foo { + t.Errorf("expected unioned config to have value [%s] at key [foo], got [%s]", f.foo, cs["foo"]) + } +} diff --git a/src/pkg/storage/storageprovider_string.go b/src/pkg/storage/storageprovider_string.go new file mode 100644 index 000000000..389dee37a --- /dev/null +++ b/src/pkg/storage/storageprovider_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=storageProvider -linecomment"; DO NOT EDIT. + +package storage + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[ProviderUnknown-0] + _ = x[ProviderS3-1] +} + +const _storageProvider_name = "Unknown ProviderS3" + +var _storageProvider_index = [...]uint8{0, 16, 18} + +func (i storageProvider) String() string { + if i < 0 || i >= storageProvider(len(_storageProvider_index)-1) { + return "storageProvider(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _storageProvider_name[_storageProvider_index[i]:_storageProvider_index[i+1]] +}