diff --git a/internal/core/basis.go b/internal/core/basis.go index 4a4a457b2..cfb437049 100644 --- a/internal/core/basis.go +++ b/internal/core/basis.go @@ -63,14 +63,17 @@ type Basis struct { // NewBasis creates a new Basis with the given options. func NewBasis(ctx context.Context, opts ...BasisOption) (b *Basis, err error) { b = &Basis{ - cache: cacher.New(), - ctx: ctx, - logger: hclog.L(), - jobInfo: &component.JobInfo{}, - projects: map[string]*Project{}, - seedValues: core.NewSeeds(), - statebag: NewStateBag(), - corePlugins: &CoreManager{}, + cache: cacher.New(), + ctx: ctx, + logger: hclog.L(), + jobInfo: &component.JobInfo{}, + projects: map[string]*Project{}, + seedValues: core.NewSeeds(), + statebag: NewStateBag(), + corePlugins: &CoreManager{ + closers: []func() error{}, + logger: hclog.L(), + }, } for _, opt := range opts { @@ -192,6 +195,33 @@ func NewBasis(ctx context.Context, opts ...BasisOption) (b *Basis, err error) { }, ) + // Configure plugins to have a core plugin manager set (used by legacy) + b.plugins.Configure( + func(i *plugin.Instance, l hclog.Logger) error { + s, ok := i.Component.(plugin.HasPluginMetadata) + if !ok { + l.Warn("plugin does not support metadata, cannot assign plugin manager", + "component", i.Type.String(), + "name", i.Name, + ) + + return nil + } + + srv, err := b.corePlugins.Servinfo(b.plugins.LegacyBroker()) + if err != nil { + l.Warn("failed to get plugin manager information", + "error", err, + ) + + return nil + } + s.SetRequestMetadata("core_plugin_manager", string(srv)) + + return nil + }, + ) + err = b.plugins.Discover(b.dir.ConfigDir().Join("plugins")) // Set seeds for any plugins that may be used diff --git a/internal/core/core_manager.go b/internal/core/core_manager.go index 8a8875165..572f21c3c 100644 --- a/internal/core/core_manager.go +++ b/internal/core/core_manager.go @@ -1,10 +1,24 @@ package core import ( + "sync" + + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-plugin" sdkcore "github.com/hashicorp/vagrant-plugin-sdk/core" + "github.com/hashicorp/vagrant-plugin-sdk/internal-shared/protomappers" + "google.golang.org/protobuf/encoding/protojson" ) type CoreManager struct { + closers []func() error // List of functions to execute on close + logger hclog.Logger // Logger for the manager + m sync.Mutex + srv []byte // Marshalled proto message for plugin manager +} + +func (m *CoreManager) closer(f func() error) { + m.closers = append(m.closers, f) } func (m *CoreManager) GetPlugin(pluginType sdkcore.Type) (plg interface{}, err error) { @@ -15,4 +29,35 @@ func (m *CoreManager) GetPlugin(pluginType sdkcore.Type) (plg interface{}, err e return } +func (m *CoreManager) Servinfo(broker *plugin.GRPCBroker) ([]byte, error) { + if m.srv != nil { + return m.srv, nil + } + + p, closer, err := protomappers.CorePluginManagerProtoDirect(m, m.logger, broker) + if err != nil { + m.logger.Warn("failed to create plugin manager grpc server", + "error", err, + ) + + return nil, err + } + + fn := func() error { + m.logger.Info("closing the GRPC server instance") + closer() + m.srv = nil + return nil + } + m.closer(fn) + + m.logger.Info("new GRPC server instance started", + "address", p.Addr, + ) + + m.srv, err = protojson.Marshal(p) + + return m.srv, err +} + var _ sdkcore.CorePluginManager = (*CoreManager)(nil) diff --git a/internal/plugin/manager.go b/internal/plugin/manager.go index 95ce1a9d6..782e351f7 100644 --- a/internal/plugin/manager.go +++ b/internal/plugin/manager.go @@ -73,6 +73,10 @@ func (m *Manager) Sub(name string) *Manager { return m } +func (m *Manager) LegacyBroker() *plugin.GRPCBroker { + return m.legacyBroker +} + // Load legacy Ruby based Vagrant plugins using a // running Vagrant runtime func (m *Manager) LoadLegacyPlugins(