vaguerent/internal/core/factory.go
2022-04-25 12:24:34 -05:00

92 lines
1.8 KiB
Go

package core
import (
"context"
"sync"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/vagrant-plugin-sdk/terminal"
"github.com/hashicorp/vagrant/internal/plugin"
"github.com/hashicorp/vagrant/internal/serverclient"
)
type Factory struct {
ctx context.Context
client *serverclient.VagrantClient
logger hclog.Logger
m sync.Mutex
plugins *plugin.Manager
registered map[string]*Basis
ui terminal.UI
}
func NewFactory(
ctx context.Context,
client *serverclient.VagrantClient,
logger hclog.Logger,
plugins *plugin.Manager,
ui terminal.UI,
) *Factory {
return &Factory{
ctx: ctx,
client: client,
logger: logger,
plugins: plugins,
ui: ui,
registered: map[string]*Basis{},
}
}
func (f *Factory) New(name string, opts ...BasisOption) (*Basis, error) {
f.m.Lock()
defer f.m.Unlock()
// If we have a name, check if it's registered and return
// the existing basis if available
if name != "" {
if b, ok := f.registered[name]; ok {
return b, nil
}
}
// Update the options to include this factory and
// our settings when creating the new basis
opts = append(opts,
WithFactory(f),
FromBasis(
&Basis{
ctx: f.ctx,
client: f.client,
logger: f.logger,
plugins: f.plugins.Sub(name),
ui: f.ui,
},
),
)
b, err := NewBasis(f.ctx, opts...)
if err != nil {
return nil, err
}
// Now there's a chance we already have this basis
// registered if the name was not provided for
// an initial lookup. If it is registered, close
// this new basis, discard, and return the
// registered one
if existingB, ok := f.registered[b.Name()]; ok {
b.Close()
return existingB, nil
}
f.registered[b.Name()] = b
b.Closer(func() error {
f.m.Lock()
defer f.m.Unlock()
delete(f.registered, b.Name())
return nil
})
return b, nil
}