From 32710b5d79679e51bbaa99de222fd2aa09cf93ad Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Fri, 13 Aug 2021 13:44:09 -0700 Subject: [PATCH] Create basis from factory and update runner to use factory --- internal/core/factory.go | 91 ++++++++++++++++++++++++++++++++++++ internal/runner/operation.go | 2 +- internal/runner/runner.go | 14 +++++- 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 internal/core/factory.go diff --git a/internal/core/factory.go b/internal/core/factory.go new file mode 100644 index 000000000..04d5fcc04 --- /dev/null +++ b/internal/core/factory.go @@ -0,0 +1,91 @@ +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, + 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 +} diff --git a/internal/runner/operation.go b/internal/runner/operation.go index db3e81e31..4bcd59299 100644 --- a/internal/runner/operation.go +++ b/internal/runner/operation.go @@ -84,7 +84,7 @@ func (r *Runner) executeJob( opts = append(opts, core.WithBasisRef(ref)) // Load our basis - b, err := core.NewBasis(ctx, opts...) + b, err := r.factory.New("", opts...) if err != nil { return } diff --git a/internal/runner/runner.go b/internal/runner/runner.go index d0f20d212..a2becbcfd 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/vagrant-plugin-sdk/terminal" intcfg "github.com/hashicorp/vagrant/internal/config" + "github.com/hashicorp/vagrant/internal/core" "github.com/hashicorp/vagrant/internal/plugin" "github.com/hashicorp/vagrant/internal/server" @@ -44,6 +45,7 @@ var ErrClosed = errors.New("runner is closed") // type Runner struct { id string + factory *core.Factory logger hclog.Logger client *serverclient.VagrantClient vagrantRubyRuntime plg.ClientProtocol @@ -116,7 +118,8 @@ func New(opts ...Option) (*Runner, error) { return nil, err } - if err := runner.plugins.LoadLegacyPlugins(runner.vagrantRubyClient, runner.vagrantRubyRuntime); err != nil { + if err := runner.plugins.LoadLegacyPlugins( + runner.vagrantRubyClient, runner.vagrantRubyRuntime); err != nil { return nil, err } @@ -132,6 +135,15 @@ func New(opts ...Option) (*Runner, error) { } } + // Add a core factory + runner.factory = core.NewFactory( + runner.ctx, + runner.client, + runner.logger, + runner.plugins, + runner.ui, + ) + return runner, nil }