Make get and list side effect free

Previously, Get and List requests could have the side effect of creating
folders. Creating required folders now only happens on save requests.
This commit is contained in:
Benedikt Kulmann
2020-06-03 13:00:14 +02:00
parent b002720b03
commit e7d3bb2063
4 changed files with 33 additions and 35 deletions

View File

@@ -279,6 +279,7 @@ func TestSaveGetSettingsBundleWithNoSettings(t *testing.T) {
cresponse, err := cl.SaveSettingsBundle(context.Background(), &createRequest)
if err != nil || (CustomError{} != testCase.expectedError) {
assert.Error(t, err)
var errorData CustomError
_ = json.Unmarshal([]byte(err.Error()), &errorData)
assert.Equal(t, testCase.expectedError.ID, errorData.ID)
@@ -625,7 +626,7 @@ func TestGetSettingsBundleCreatesFolder(t *testing.T) {
getRequest := proto.GetSettingsBundleRequest{Identifier: &identifier}
_, _ = cl.GetSettingsBundle(context.Background(), &getRequest)
assert.DirExists(t, "ocis-settings-store/bundles/not-existing-extension")
assert.NoDirExists(t, "ocis-settings-store/bundles/not-existing-extension")
assert.NoFileExists(t, "ocis-settings-store/bundles/not-existing-extension/not-existing-bundle.json")
_ = os.RemoveAll("ocis-settings-store")
}
@@ -901,7 +902,7 @@ func TestListSettingsBundlesOfNonExistingExtension(t *testing.T) {
response, err := cl.ListSettingsBundles(context.Background(), &listRequest)
assert.NoError(t, err)
assert.Empty(t, response.String())
assert.DirExists(t, "ocis-settings-store/bundles")
assert.NoDirExists(t, "ocis-settings-store/bundles")
assert.NoDirExists(t, "ocis-settings-store/bundles/does-not-exist")
}

View File

@@ -10,11 +10,11 @@ import (
// 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()
var records []*proto.SettingsBundle
bundlesFolder := s.buildFolderPathBundles(false)
extensionFolders, err := ioutil.ReadDir(bundlesFolder)
if err != nil {
s.Logger.Err(err).Msgf("error reading %v", bundlesFolder)
return nil, err
return records, nil
}
if len(identifier.Extension) < 1 {
@@ -22,7 +22,6 @@ func (s Store) ListBundles(identifier *proto.Identifier) ([]*proto.SettingsBundl
} 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())
bundleFiles, err := ioutil.ReadDir(extensionPath)
@@ -50,7 +49,7 @@ func (s Store) ListBundles(identifier *proto.Identifier) ([]*proto.SettingsBundl
// ReadBundle tries to find a bundle by the given identifier within the mountPath.
// Extension and BundleKey within the identifier are required.
func (s Store) ReadBundle(identifier *proto.Identifier) (*proto.SettingsBundle, error) {
filePath := s.buildFilePathFromBundleArgs(identifier.Extension, identifier.BundleKey)
filePath := s.buildFilePathFromBundleArgs(identifier.Extension, identifier.BundleKey, false)
record := proto.SettingsBundle{}
if err := s.parseRecordFromFile(&record, filePath); err != nil {
return nil, err
@@ -63,7 +62,7 @@ func (s Store) ReadBundle(identifier *proto.Identifier) (*proto.SettingsBundle,
// WriteBundle writes the given record into a file within the mountPath
// Extension and BundleKey within the record identifier are required.
func (s Store) WriteBundle(record *proto.SettingsBundle) (*proto.SettingsBundle, error) {
filePath := s.buildFilePathFromBundle(record)
filePath := s.buildFilePathFromBundle(record, true)
if err := s.writeRecordToFile(record, filePath); err != nil {
return nil, err
}

View File

@@ -10,41 +10,40 @@ import (
const folderNameBundles = "bundles"
const folderNameValues = "values"
// Builds the folder path for storing settings bundles
func (s Store) buildFolderPathBundles() string {
// Builds the folder path for storing settings bundles. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFolderPathBundles(mkdir bool) string {
folderPath := path.Join(s.mountPath, folderNameBundles)
s.ensureFolderExists(folderPath)
if mkdir {
s.ensureFolderExists(folderPath)
}
return folderPath
}
// Builds a unique file name from the given settings bundle
func (s Store) buildFilePathFromBundle(bundle *proto.SettingsBundle) string {
return s.buildFilePathFromBundleArgs(bundle.Identifier.Extension, bundle.Identifier.BundleKey)
// Builds a unique file name from the given settings bundle. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFilePathFromBundle(bundle *proto.SettingsBundle, mkdir bool) string {
return s.buildFilePathFromBundleArgs(bundle.Identifier.Extension, bundle.Identifier.BundleKey, mkdir)
}
// Builds a unique file name from the given params
func (s Store) buildFilePathFromBundleArgs(extension string, bundleKey string) string {
// Builds a unique file name from the given params. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFilePathFromBundleArgs(extension string, bundleKey string, mkdir bool) string {
extensionFolder := path.Join(s.mountPath, folderNameBundles, extension)
s.ensureFolderExists(extensionFolder)
if mkdir {
s.ensureFolderExists(extensionFolder)
}
return path.Join(extensionFolder, bundleKey+".json")
}
// // Builds the folder path for storing settings values
// func (s Store) buildFolderPathValues() string {
// folderPath := path.Join(s.mountPath, folderNameValues)
// s.ensureFolderExists(folderPath)
// return folderPath
// }
// Builds a unique file name from the given settings value
func (s Store) buildFilePathFromValue(value *proto.SettingsValue) string {
return s.buildFilePathFromValueArgs(value.Identifier.AccountUuid, value.Identifier.Extension, value.Identifier.BundleKey)
// Builds a unique file name from the given settings value. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFilePathFromValue(value *proto.SettingsValue, mkdir bool) string {
return s.buildFilePathFromValueArgs(value.Identifier.AccountUuid, value.Identifier.Extension, value.Identifier.BundleKey, mkdir)
}
// Builds a unique file name from the given params
func (s Store) buildFilePathFromValueArgs(accountUUID string, extension string, bundleKey string) string {
// Builds a unique file name from the given params. If mkdir is true, folders in the path will be created if necessary.
func (s Store) buildFilePathFromValueArgs(accountUUID string, extension string, bundleKey string, mkdir bool) string {
extensionFolder := path.Join(s.mountPath, folderNameValues, accountUUID, extension)
s.ensureFolderExists(extensionFolder)
if mkdir {
s.ensureFolderExists(extensionFolder)
}
return path.Join(extensionFolder, bundleKey+".json")
}

View File

@@ -14,7 +14,7 @@ import (
// ReadValue tries to find a value by the given identifier attributes within the mountPath
// All identifier fields are required.
func (s Store) ReadValue(identifier *proto.Identifier) (*proto.SettingsValue, error) {
filePath := s.buildFilePathFromValueArgs(identifier.AccountUuid, identifier.Extension, identifier.BundleKey)
filePath := s.buildFilePathFromValueArgs(identifier.AccountUuid, identifier.Extension, identifier.BundleKey, false)
values, err := s.readValuesMapFromFile(filePath)
if err != nil {
return nil, err
@@ -29,7 +29,7 @@ func (s Store) ReadValue(identifier *proto.Identifier) (*proto.SettingsValue, er
// WriteValue writes the given SettingsValue into a file within the mountPath
// All identifier fields within the value are required.
func (s Store) WriteValue(value *proto.SettingsValue) (*proto.SettingsValue, error) {
filePath := s.buildFilePathFromValue(value)
filePath := s.buildFilePathFromValue(value, true)
values, err := s.readValuesMapFromFile(filePath)
if err != nil {
return nil, err
@@ -50,7 +50,6 @@ func (s Store) ListValues(identifier *proto.Identifier) ([]*proto.SettingsValue,
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 {
@@ -62,7 +61,7 @@ func (s Store) ListValues(identifier *proto.Identifier) ([]*proto.SettingsValue,
return nil
}); err != nil {
s.Logger.Err(err).Msgf("error reading %v", accountFolderPath)
return nil, err
return values, nil
}
} else if len(identifier.BundleKey) < 1 {
extensionPath := path.Join(accountFolderPath, identifier.Extension)
@@ -74,7 +73,7 @@ func (s Store) ListValues(identifier *proto.Identifier) ([]*proto.SettingsValue,
return nil
}); err != nil {
s.Logger.Err(err).Msgf("error reading %v", extensionPath)
return nil, err
return values, nil
}
} else {
bundlePath := path.Join(accountFolderPath, identifier.Extension, identifier.BundleKey+".json")