vaguerent/internal/core/component_creator.go
2022-04-25 12:23:57 -05:00

125 lines
2.7 KiB
Go

package core
import (
"context"
// "fmt"
"github.com/hashicorp/go-argmapper"
"github.com/hashicorp/vagrant-plugin-sdk/component"
"github.com/hashicorp/vagrant/internal/config"
"github.com/hashicorp/vagrant/internal/plugin"
"github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
)
type Component struct {
Value interface{}
Info *vagrant_server.Component
// These fields can be accessed internally
hooks map[string][]*config.Hook
labels map[string]string
mappers []*argmapper.Func
// These are private, please do not access them ever except as an
// internal Component implementation detail.
closed bool
plugin *plugin.Instance
}
// Close cleans up any resources associated with the Component. Close should
// always be called when the component is done being used.
func (c *Component) Close() error {
if c == nil {
return nil
}
// If we closed already do nothing.
if c.closed {
return nil
}
c.closed = true
if c.plugin != nil {
c.plugin.Close()
}
return nil
}
// componentCreator represents the configuration to initialize the component
// for a given application.
type componentCreator struct {
Type component.Type
}
// componentCreatorMap contains all the components that can be initialized
// for an app.
var componentCreatorMap = map[component.Type]*componentCreator{
component.CommandType: {
Type: component.CommandType,
},
component.ProviderType: {
Type: component.ProviderType,
},
component.HostType: {
Type: component.HostType,
},
}
// Create creates the component of the given type.
func (cc *componentCreator) Create(
ctx context.Context,
scope interface{},
pluginName string,
) (*Component, error) {
s, ok := scope.(interface {
startPlugin(context.Context, component.Type, string) (*plugin.Instance, error)
})
if !ok {
panic("the scope provided is invalid")
}
// Start the plugin
pinst, err := s.startPlugin(
ctx,
cc.Type,
pluginName,
)
if err != nil {
return nil, err
}
// TODO: configure
// If we have a config, configure
// Configure the component. This will handle all the cases where no
// config is given but required, vice versa, and everything in between.
// diag := component.Configure(pinst.Component, opCfg.Use.Body, hclCtx)
// if diag.HasErrors() {
// pinst.Close()
// return nil, diag
// }
// TODO: Setup hooks
hooks := map[string][]*config.Hook{}
// for _, h := range opCfg.Hooks {
// hooks[h.When] = append(hooks[h.When], h)
// }
return &Component{
Value: pinst.Component,
Info: &vagrant_server.Component{
Type: vagrant_server.Component_Type(cc.Type),
Name: pluginName,
},
hooks: hooks,
mappers: pinst.Mappers,
plugin: pinst,
}, nil
}
type pluginer interface {
startPlugin(context.Context, component.Type, string) (*plugin.Instance, error)
}