Settings values protobuf and service
This commit is contained in:
@@ -9,8 +9,8 @@ import (
|
||||
"path"
|
||||
)
|
||||
|
||||
// ListByExtension returns all bundles in the mountPath folder belonging to the given extension
|
||||
func (s Store) ListByExtension(extension string) ([]*proto.SettingsBundle, error) {
|
||||
// ListBundles returns all bundles in the mountPath folder belonging to the given extension
|
||||
func (s Store) ListBundles(identifier *proto.Identifier) ([]*proto.SettingsBundle, error) {
|
||||
bundlesFolder := s.buildFolderPathBundles()
|
||||
extensionFolders, err := ioutil.ReadDir(bundlesFolder)
|
||||
if err != nil {
|
||||
@@ -18,7 +18,11 @@ func (s Store) ListByExtension(extension string) ([]*proto.SettingsBundle, error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.Logger.Info().Msgf("listing bundles by extension %v", extension)
|
||||
if len(identifier.Extension) < 1 {
|
||||
s.Logger.Info().Msg("listing all bundles")
|
||||
} else {
|
||||
s.Logger.Info().Msgf("listing bundles by extension %v", identifier.Extension)
|
||||
}
|
||||
var records []*proto.SettingsBundle
|
||||
for _, extensionFolder := range extensionFolders {
|
||||
extensionPath := path.Join(bundlesFolder, extensionFolder.Name())
|
||||
@@ -27,7 +31,7 @@ func (s Store) ListByExtension(extension string) ([]*proto.SettingsBundle, error
|
||||
for _, bundleFile := range bundleFiles {
|
||||
record := proto.SettingsBundle{}
|
||||
err = s.parseRecordFromFile(&record, path.Join(extensionPath, bundleFile.Name()))
|
||||
if err == nil && (len(extension) == 0 || extension == record.Extension) {
|
||||
if err == nil && (len(identifier.Extension) == 0 || identifier.Extension == record.Identifier.Extension) {
|
||||
records = append(records, &record)
|
||||
}
|
||||
}
|
||||
@@ -40,13 +44,13 @@ func (s Store) ListByExtension(extension string) ([]*proto.SettingsBundle, error
|
||||
}
|
||||
|
||||
// Read tries to find a bundle by the given extension and key within the mountPath
|
||||
func (s Store) ReadBundle(extension string, bundleKey string) (*proto.SettingsBundle, error) {
|
||||
if len(extension) < 1 || len(bundleKey) < 1 {
|
||||
func (s Store) ReadBundle(identifier *proto.Identifier) (*proto.SettingsBundle, error) {
|
||||
if len(identifier.Extension) < 1 || len(identifier.BundleKey) < 1 {
|
||||
s.Logger.Error().Msg("extension and bundleKey cannot be empty")
|
||||
return nil, gstatus.Error(codes.InvalidArgument, "Missing a required identifier attribute")
|
||||
}
|
||||
|
||||
filePath := s.buildFilePathFromBundleArgs(extension, bundleKey)
|
||||
filePath := s.buildFilePathFromBundleArgs(identifier.Extension, identifier.BundleKey)
|
||||
record := proto.SettingsBundle{}
|
||||
if err := s.parseRecordFromFile(&record, filePath); err != nil {
|
||||
return nil, err
|
||||
@@ -58,7 +62,7 @@ func (s Store) ReadBundle(extension string, bundleKey string) (*proto.SettingsBu
|
||||
|
||||
// Write writes the given record into a file within the mountPath
|
||||
func (s Store) WriteBundle(record *proto.SettingsBundle) (*proto.SettingsBundle, error) {
|
||||
if len(record.Extension) < 1 || len(record.BundleKey) < 1 {
|
||||
if len(record.Identifier.Extension) < 1 || len(record.Identifier.BundleKey) < 1 {
|
||||
s.Logger.Error().Msg("extension and bundleKey cannot be empty")
|
||||
return nil, gstatus.Error(codes.InvalidArgument, "Missing a required identifier attribute")
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func (s Store) buildFolderPathBundles() string {
|
||||
|
||||
// Builds a unique file name from the given settings bundle
|
||||
func (s Store) buildFilePathFromBundle(bundle *proto.SettingsBundle) string {
|
||||
return s.buildFilePathFromBundleArgs(bundle.Extension, bundle.BundleKey)
|
||||
return s.buildFilePathFromBundleArgs(bundle.Identifier.Extension, bundle.Identifier.BundleKey)
|
||||
}
|
||||
|
||||
// Builds a unique file name from the given params
|
||||
@@ -37,7 +37,7 @@ func (s Store) buildFolderPathValues() string {
|
||||
|
||||
// Builds a unique file name from the given settings value
|
||||
func (s Store) buildFilePathFromValue(value *proto.SettingsValue) string {
|
||||
return s.buildFilePathFromValueArgs(value.AccountUuid, value.Extension, value.BundleKey)
|
||||
return s.buildFilePathFromValueArgs(value.Identifier.AccountUuid, value.Identifier.Extension, value.Identifier.BundleKey)
|
||||
}
|
||||
|
||||
// Builds a unique file name from the given params
|
||||
|
||||
@@ -6,31 +6,33 @@ import (
|
||||
"google.golang.org/grpc/codes"
|
||||
gstatus "google.golang.org/grpc/status"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Read tries to find a value by the given identifier attributes within the mountPath
|
||||
func (s Store) ReadValue(accountUuid string, extension string, bundleKey string, settingKey string) (*proto.SettingsValue, error) {
|
||||
if len(accountUuid) < 1 || len(extension) < 1 || len(bundleKey) < 1 || len(settingKey) < 1 {
|
||||
s.Logger.Error().Msg("account, extension, bundle and setting are required")
|
||||
// Tries to find a value by the given identifier attributes within the mountPath
|
||||
func (s Store) ReadValue(identifier *proto.Identifier) (*proto.SettingsValue, error) {
|
||||
if len(identifier.AccountUuid) < 1 || len(identifier.Extension) < 1 || len(identifier.BundleKey) < 1 || len(identifier.SettingKey) < 1 {
|
||||
s.Logger.Error().Msg("account-uuid, extension, bundle and setting are required")
|
||||
return nil, gstatus.Errorf(codes.InvalidArgument, "Missing a required identifier attribute")
|
||||
}
|
||||
|
||||
filePath := s.buildFilePathFromValueArgs(accountUuid, extension, bundleKey)
|
||||
filePath := s.buildFilePathFromValueArgs(identifier.AccountUuid, identifier.Extension, identifier.BundleKey)
|
||||
values, err := s.readValuesMapFromFile(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if value := values.Values[settingKey]; value != nil {
|
||||
if value := values.Values[identifier.SettingKey]; value != nil {
|
||||
return value, nil
|
||||
}
|
||||
// TODO: we want to return sensible defaults here, when the value was not found
|
||||
return nil, gstatus.Error(codes.NotFound, "SettingsValue not set")
|
||||
}
|
||||
|
||||
// Write writes the given SettingsValue into a file within the mountPath
|
||||
// Writes the given SettingsValue into a file within the mountPath
|
||||
func (s Store) WriteValue(value *proto.SettingsValue) (*proto.SettingsValue, error) {
|
||||
if len(value.AccountUuid) < 1 || len(value.Extension) < 1 || len(value.BundleKey) < 1 || len(value.SettingKey) < 1 {
|
||||
s.Logger.Error().Msg("account, extension, bundle and setting are required")
|
||||
if len(value.Identifier.AccountUuid) < 1 || len(value.Identifier.Extension) < 1 || len(value.Identifier.BundleKey) < 1 || len(value.Identifier.SettingKey) < 1 {
|
||||
s.Logger.Error().Msg("account-uuid, extension, bundle and setting are required")
|
||||
return nil, gstatus.Errorf(codes.InvalidArgument, "Missing a required identifier attribute")
|
||||
}
|
||||
|
||||
@@ -39,13 +41,72 @@ func (s Store) WriteValue(value *proto.SettingsValue) (*proto.SettingsValue, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values.Values[value.SettingKey] = value
|
||||
values.Values[value.Identifier.SettingKey] = value
|
||||
if err := s.writeRecordToFile(values, filePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// Reads all values within the scope of the given identifier
|
||||
func (s Store) ListValues(identifier *proto.Identifier) ([]*proto.SettingsValue, error) {
|
||||
if len(identifier.AccountUuid) < 1 {
|
||||
s.Logger.Error().Msg("account-uuid is required")
|
||||
return nil, gstatus.Errorf(codes.InvalidArgument, "Missing a required identifier attribute")
|
||||
}
|
||||
|
||||
accountFolderPath := path.Join(s.mountPath, folderNameValues, identifier.AccountUuid)
|
||||
var values []*proto.SettingsValue
|
||||
if _, err := os.Stat(accountFolderPath); err != nil {
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// TODO: might be a good idea to do this non-hierarchical. i.e. allowing all fragments in the identifier being set or not.
|
||||
// depending on the set values in the identifier arg, collect all SettingValues files for the account
|
||||
var valueFilePaths []string
|
||||
if len(identifier.Extension) < 1 {
|
||||
if err := filepath.Walk(accountFolderPath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valueFilePaths = append(valueFilePaths, path)
|
||||
return nil
|
||||
}); err != nil {
|
||||
s.Logger.Err(err).Msgf("error reading %v", accountFolderPath)
|
||||
return nil, err
|
||||
}
|
||||
} else if len(identifier.BundleKey) < 1 {
|
||||
extensionPath := path.Join(accountFolderPath, identifier.Extension)
|
||||
if err := filepath.Walk(extensionPath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valueFilePaths = append(valueFilePaths, path)
|
||||
return nil
|
||||
}); err != nil {
|
||||
s.Logger.Err(err).Msgf("error reading %v", extensionPath)
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
bundlePath := path.Join(accountFolderPath, identifier.Extension, identifier.BundleKey+".json")
|
||||
valueFilePaths = append(valueFilePaths, bundlePath)
|
||||
}
|
||||
|
||||
// parse the SettingValues from the collected files
|
||||
for _, filePath := range valueFilePaths {
|
||||
bundleValues, err := s.readValuesMapFromFile(filePath)
|
||||
if err != nil {
|
||||
s.Logger.Err(err).Msgf("error reading %v", filePath)
|
||||
} else {
|
||||
for _, value := range bundleValues.Values {
|
||||
values = append(values, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return values, nil
|
||||
}
|
||||
|
||||
// Reads SettingsValues as map from the given file or returns an empty map if the file doesn't exist.
|
||||
func (s Store) readValuesMapFromFile(filePath string) (*proto.SettingsValues, error) {
|
||||
values := &proto.SettingsValues{}
|
||||
err := s.parseRecordFromFile(values, filePath)
|
||||
|
||||
Reference in New Issue
Block a user