Basic service boilerplate for settings bundles

This commit is contained in:
Benedikt Kulmann
2020-04-16 10:07:45 +02:00
parent a8af03c338
commit 5b89729d1e
18 changed files with 1006 additions and 141 deletions
+145
View File
@@ -0,0 +1,145 @@
// Package store implements the go-micro store interface
package store
import (
"encoding/json"
"fmt"
olog "github.com/owncloud/ocis-pkg/v2/log"
"github.com/owncloud/ocis-settings/pkg/config"
"github.com/owncloud/ocis-settings/pkg/proto/v0"
"github.com/owncloud/ocis-settings/pkg/settings"
"io/ioutil"
"os"
"path"
"strings"
)
var (
// StoreName is the default name for the settings store
StoreName = "ocis-settings-store"
managerName = "filesystem"
emptyKeyError = "key cannot be empty"
)
// Store interacts with the filesystem to manage settings information
type Store struct {
mountPath string
Logger olog.Logger
}
// New creates a new store
func New(cfg *config.Config) settings.Manager {
s := Store{}
dest := path.Join(cfg.Storage.RootMountPath, StoreName)
if _, err := os.Stat(dest); err != nil {
s.Logger.Info().Msgf("creating container on %v", dest)
err := os.MkdirAll(dest, 0700)
if err != nil {
s.Logger.Err(err).Msgf("providing container on %v", dest)
}
}
s.mountPath = dest
return &s
}
// List returns all the bundles in the mountPath folder
func (s Store) List() ([]*proto.SettingsBundle, error) {
records := []*proto.SettingsBundle{}
bundles, err := ioutil.ReadDir(s.mountPath)
if err != nil {
s.Logger.Err(err).Msgf("error reading %v", s.mountPath)
return nil, err
}
s.Logger.Info().Msg("listing bundles")
for _, v := range bundles {
records = append(records, parseFileName(v.Name()))
}
return records, nil
}
// ListByExtension returns all bundles in the mountPath folder belonging to the given extension
func (s Store) ListByExtension(extension string) ([]*proto.SettingsBundle, error) {
records := []*proto.SettingsBundle{}
bundles, err := ioutil.ReadDir(s.mountPath)
if err != nil {
s.Logger.Err(err).Msgf("error reading %v", s.mountPath)
return nil, err
}
s.Logger.Info().Msgf("listing bundles by extension %v", extension)
for _, v := range bundles {
record := parseFileName(v.Name())
if record.Extension == extension {
records = append(records, record)
}
}
return records, nil
}
// Read tries to find a bundle by the given extension and key within the mountPath
func (s Store) Read(extension string, key string) (*proto.SettingsBundle, error) {
fileName := buildFileNameFromData(extension, key)
contents, err := ioutil.ReadFile(path.Join(s.mountPath, fileName))
if err != nil {
s.Logger.Err(err).Msgf("error reading contents for extension %v and key %v: file not found", extension, key)
return nil, err
}
record := proto.SettingsBundle{}
if err = json.Unmarshal(contents, &record); err != nil {
s.Logger.Err(err).Msg("error unmarshalling record")
return nil, err
}
return &record, nil
}
// Write writes the given record into a file within the mountPath
func (s Store) Write(rec *proto.SettingsBundle) (*proto.SettingsBundle, error) {
if len(rec.Key) < 1 {
s.Logger.Error().Msg("key cannot be empty")
return nil, fmt.Errorf(emptyKeyError)
}
contents, err := json.Marshal(rec)
if err != nil {
s.Logger.Err(err).Msg("record could not be marshalled")
return nil, err
}
recordPath := path.Join(s.mountPath, buildFileNameFromBundle(rec))
if err := ioutil.WriteFile(recordPath, contents, 0644); err != nil {
return nil, err
}
s.Logger.Info().Msgf("%v bytes written to %v", len(contents), recordPath)
return rec, nil
}
// Builds a unique file name from the given bundle
func buildFileNameFromBundle(bundle *proto.SettingsBundle) string {
return buildFileNameFromData(bundle.Extension, bundle.Key)
}
// Builds a unique file name from the given params
func buildFileNameFromData(extension string, key string) string {
return extension + "__" + key + ".json"
}
// Extracts extension and key from the given fileName and builds a (minimalistic) bundle from it
func parseFileName(fileName string) *proto.SettingsBundle {
parts := strings.Split(strings.Replace(fileName, ".json", "", 1), "__")
return &proto.SettingsBundle{
Key: parts[1],
Extension: parts[0],
}
}
func init() {
settings.Registry[managerName] = New
}
+6
View File
@@ -0,0 +1,6 @@
package store
import (
// init filesystem store
_ "github.com/owncloud/ocis-settings/pkg/store/filesystem"
)