diff --git a/internal/core/basis.go b/internal/core/basis.go index ee5a8b0d4..6f63df615 100644 --- a/internal/core/basis.go +++ b/internal/core/basis.go @@ -530,6 +530,50 @@ func (b *Basis) Run(ctx context.Context, task *vagrant_server.Task) (err error) return } +type HasParents interface { + Parents() ([]string, error) +} + +func (b *Basis) loadParentPlugins(p *plugin.Plugin, typ component.Type) (err error) { + plg, err := p.InstanceOf(typ) + if err != nil { + panic(err) + } + h, ok := plg.Component.(HasParents) + if !ok { + b.logger.Debug("Plugin of type ", typ, " does not have Parents") + return nil + } + parents, err := h.Parents() + if err != nil { + panic(err) + } + if len(parents) == len(p.ParentPlugins) { + return + } + // TODO: avoid making duplicate entries + for _, parent := range parents { + // Avoid looping if a plugin name has erronously been added to the parent list + if parent == p.Name { + continue + } + b.logger.Debug("Loading parents: ", parent) + parentPlugin, err := b.plugins.Find(parent, typ) + if err != nil { + b.logger.Debug("Error finding parent plugin: ", parent) + continue + } + _, err = parentPlugin.InstanceOf(typ) + if err != nil { + b.logger.Debug("Error loading parent plugin: ", parent) + } + p.ParentPlugins = append(p.ParentPlugins, parentPlugin) + b.loadParentPlugins(parentPlugin, typ) + } + p.SetParentPlugins(typ) + return +} + // Load a specific component func (b *Basis) component( ctx context.Context, // context for the plugin @@ -545,6 +589,10 @@ func (b *Basis) component( if err != nil { return nil, err } + + // Make sure parent plugins get loaded + b.loadParentPlugins(p, typ) + c, err := p.InstanceOf(typ) if err != nil { return nil, err diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go index faf58f6e3..721d72600 100644 --- a/internal/plugin/plugin.go +++ b/internal/plugin/plugin.go @@ -34,12 +34,13 @@ var ( ) type Plugin struct { - Builtin bool // Flags if this plugin is a builtin plugin - Client plugin.ClientProtocol // Client connection to plugin - Location string // Location of the plugin (generally path to binary) - Name string // Name of the plugin - Types []component.Type // Component types supported by this plugin - Cache cacher.Cache + Builtin bool // Flags if this plugin is a builtin plugin + Client plugin.ClientProtocol // Client connection to plugin + Location string // Location of the plugin (generally path to binary) + Name string // Name of the plugin + Types []component.Type // Component types supported by this plugin + Cache cacher.Cache + ParentPlugins []*Plugin closers []func() error components map[component.Type]*Instance @@ -78,6 +79,31 @@ func (p *Plugin) Close() (err error) { return } +func (p *Plugin) SetParentPlugins(typ component.Type) { + i := p.components[typ] + if i == nil { + return + } + pluginWithParent, ok := i.Component.(PluginWithParent) + if !ok { + p.logger.Warn("plugin does not support parents", + "component", typ.String(), + "name", p.Name) + + } else { + p.logger.Info("setting plugin parents", + "component", typ.String(), + "name", p.Name) + + parentComponents := []interface{}{} + for _, pp := range p.ParentPlugins { + parentComponents = append(parentComponents, pp.components[typ].Component) + } + // TODO: set parent plugins + pluginWithParent.SetParentPlugins(parentComponents) + } +} + // Get specific component type from plugin func (p *Plugin) InstanceOf( c component.Type, @@ -172,3 +198,7 @@ func (p *Plugin) types() []string { } return result } + +type PluginWithParent interface { + SetParentPlugins([]interface{}) +}