package nucleus import ( "errors" "code.fbi.h-da.de/danet/gosdn/controller/event" eventInterfaces "code.fbi.h-da.de/danet/gosdn/controller/interfaces/event" "code.fbi.h-da.de/danet/gosdn/controller/interfaces/plugin" "code.fbi.h-da.de/danet/gosdn/controller/store" "github.com/google/uuid" hcplugin "github.com/hashicorp/go-plugin" log "github.com/sirupsen/logrus" ) const ( // PluginEventTopic is the used topic for plugin related entity changes. PluginEventTopic = "plugin" ) // PluginService provides a plugin service implementation. type PluginService struct { pluginStore plugin.Store eventService eventInterfaces.Service createPluginFromStoreFn func(plugin.LoadedPlugin) (plugin.Plugin, error) } // NewPluginService creates a plugin service. func NewPluginService(pluginStore plugin.Store, eventService eventInterfaces.Service, createPluginFromStoreFn func(plugin.LoadedPlugin) (plugin.Plugin, error)) plugin.Service { return &PluginService{ pluginStore: pluginStore, eventService: eventService, createPluginFromStoreFn: createPluginFromStoreFn, } } // Get takes a Plugin's UUID or name and returns the Plugin. func (s *PluginService) Get(query store.Query) (plugin.Plugin, error) { loadedPlugin, err := s.pluginStore.Get(query) if err != nil { return nil, err } plugin, err := s.createPluginFromStore(loadedPlugin) if err != nil { return nil, err } return plugin, nil } // GetAll returns all stored plugins. func (s *PluginService) GetAll() ([]plugin.Plugin, error) { var plugins []plugin.Plugin loadedPlugins, err := s.pluginStore.GetAll() if err != nil { return nil, err } for _, loadedPlugin := range loadedPlugins { plugin, err := s.createPluginFromStore(loadedPlugin) if err != nil { return nil, err } plugins = append(plugins, plugin) } return plugins, nil } // Add adds a plugin to the plugin store. func (s *PluginService) Add(pluginToAdd plugin.Plugin) error { err := s.pluginStore.Add(pluginToAdd) if err != nil { return err } if err := s.eventService.PublishEvent(PluginEventTopic, event.NewAddEvent(pluginToAdd.ID())); err != nil { log.Error(err) } return nil } // Delete deletes a plugin from the plugin store. func (s *PluginService) Delete(pluginToDelete plugin.Plugin) error { err := s.pluginStore.Delete(pluginToDelete) if err != nil { return err } // stop the plugin pluginToDelete.GetClient().Kill() if err := s.eventService.PublishEvent(PluginEventTopic, event.NewDeleteEvent(pluginToDelete.ID())); err != nil { log.Error(err) } return nil } func (s *PluginService) createPluginFromStore(loadedPlugin plugin.LoadedPlugin) (plugin.Plugin, error) { plugin, err := s.createPluginFromStoreFn(loadedPlugin) if err != nil { if errors.Is(err, hcplugin.ErrProcessNotFound) { plugin, err = NewPlugin(uuid.MustParse(loadedPlugin.ID)) if err != nil { return nil, err } err := s.pluginStore.Update(plugin) if err != nil { return nil, err } } else { return nil, err } } return plugin, nil }