Skip to content
Snippets Groups Projects
pluginFilesystemStore.go 4.11 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	"context"
    
    	"encoding/json"
    	"os"
    	"sync"
    
    	"code.fbi.h-da.de/danet/gosdn/controller/customerrs"
    	"code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin"
    	"code.fbi.h-da.de/danet/gosdn/controller/store"
    
    	log "github.com/sirupsen/logrus"
    )
    
    // FilesystemPluginStore is used to store Plugins.
    type FilesystemPluginStore struct {
    	fileMutex        sync.Mutex
    	pathToPluginFile string
    }
    
    // NewFilesystemPluginStore returns a filesystem implementation for a plugin store.
    func NewFilesystemPluginStore() plugin.Store {
    	if err := store.EnsureFilesystemStorePathExists(store.PluginFilenameSuffix); err != nil {
    		log.Error(err)
    	}
    
    	return &FilesystemPluginStore{
    		pathToPluginFile: store.GetCompletePathToFileStore(store.PluginFilenameSuffix),
    		fileMutex:        sync.Mutex{},
    	}
    }
    
    func (s *FilesystemPluginStore) readAllPluginsFromFile() ([]plugin.LoadedPlugin, error) {
    	var loadedPlugins []plugin.LoadedPlugin
    
    	content, err := os.ReadFile(s.pathToPluginFile)
    	if err != nil {
    		return nil, err
    	}
    
    	err = json.Unmarshal(content, &loadedPlugins)
    	if err != nil {
    		return nil, err
    	}
    	return loadedPlugins, nil
    }
    
    func (s *FilesystemPluginStore) writeAllPluginsToFile(plugins []plugin.LoadedPlugin) error {
    	serializedData, err := json.Marshal(plugins)
    	if err != nil {
    		return err
    	}
    
    	err = os.WriteFile(s.pathToPluginFile, serializedData, 0600)
    	if err != nil {
    		return err
    	}
    	return nil
    }
    
    // Add adds a Plugin.
    
    func (s *FilesystemPluginStore) Add(ctx context.Context, pluginToAdd plugin.Plugin) error {
    
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	plugins, err := s.readAllPluginsFromFile()
    	if err != nil {
    		return err
    	}
    
    	var loadedPlugin plugin.LoadedPlugin
    	loadedPlugin, err = store.TransformObjectToLoadedObject[plugin.Plugin, plugin.LoadedPlugin](pluginToAdd)
    	if err != nil {
    		return err
    	}
    
    	plugins = append(plugins, loadedPlugin)
    
    	err = s.writeAllPluginsToFile(plugins)
    	if err != nil {
    		return err
    	}
    
    	return nil
    }
    
    // Update updates an existing plugin.
    
    func (s *FilesystemPluginStore) Update(ctx context.Context, pluginToUpdate plugin.Plugin) error {
    
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	loadedPluginToUpdate, err := store.TransformObjectToLoadedObject[plugin.Plugin, plugin.LoadedPlugin](pluginToUpdate)
    	if err != nil {
    		return err
    	}
    
    	plugins, err := s.readAllPluginsFromFile()
    	if err != nil {
    		return err
    	}
    
    	for i, plugin := range plugins {
    		if plugin.ID == pluginToUpdate.ID().String() {
    			plugins[i] = loadedPluginToUpdate
    			err = s.writeAllPluginsToFile(plugins)
    			if err != nil {
    				return err
    			}
    			return nil
    		}
    	}
    
    	return &customerrs.CouldNotUpdateError{Identifier: pluginToUpdate.ID(), Type: pluginToUpdate, Err: err}
    }
    
    // Delete deletes an Plugin.
    
    func (s *FilesystemPluginStore) Delete(ctx context.Context, pluginToDelete plugin.Plugin) error {
    
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	plugins, err := s.readAllPluginsFromFile()
    	if err != nil {
    		return err
    	}
    
    	for i, plugin := range plugins {
    		if plugin.ID == pluginToDelete.ID().String() {
    			//remove item from slice
    			plugins[i] = plugins[len(plugins)-1]
    			plugins = plugins[:len(plugins)-1]
    
    			err = s.writeAllPluginsToFile(plugins)
    			if err != nil {
    				return err
    			}
    
    			return nil
    		}
    	}
    	return &customerrs.CouldNotDeleteError{Identifier: pluginToDelete.ID(), Type: pluginToDelete, Err: err}
    }
    
    // Get takes a Plugin's UUID or name and returns the Plugin. If the requested
    // Plugin does not exist an error is returned.
    
    func (s *FilesystemPluginStore) Get(ctx context.Context, query store.Query) (plugin.LoadedPlugin, error) {
    
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	var plugin plugin.LoadedPlugin
    
    	plugins, err := s.readAllPluginsFromFile()
    	if err != nil {
    		return plugin, err
    	}
    
    	for _, plugin := range plugins {
    		if plugin.ID == query.ID.String() {
    			return plugin, nil
    		}
    	}
    
    	return plugin, &customerrs.CouldNotFindError{ID: query.ID, Name: query.Name}
    }
    
    // GetAll returns all Plugins.
    
    func (s *FilesystemPluginStore) GetAll(ctx context.Context) ([]plugin.LoadedPlugin, error) {
    
    	s.fileMutex.Lock()
    	defer s.fileMutex.Unlock()
    
    	plugins, err := s.readAllPluginsFromFile()
    
    	return plugins, err
    }