From 80b3fcf93e98678baf223bee31077ca18170fc4b Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 31 Aug 2021 10:58:05 -0700 Subject: [PATCH] core: Replace contextComponentFactory with contextPlugins In the v0.12 timeframe we made contextComponentFactory an interface with the expectation that we'd write mocks of it for tests, but in practice we ended up just always using the same "basicComponentFactory" implementation throughout. In the interests of simplification then, here we replace that interface and its sole implementation with a new concrete struct type contextPlugins. Along with the general benefit that this removes an unneeded indirection, this also means that we can add additional methods to the struct type without the usual restriction that interface types prefer to be small. In particular, in a future commit I'm planning to add methods for loading provider and provisioner schemas, working with the currently-unused new fields this commit has included in contextPlugins, as compared to its predecessor basicComponentFactory. --- internal/command/import_test.go | 2 +- internal/terraform/context.go | 11 +-- internal/terraform/context_apply.go | 2 +- internal/terraform/context_components.go | 46 --------- internal/terraform/context_eval.go | 8 +- internal/terraform/context_import.go | 2 +- internal/terraform/context_plan.go | 6 +- internal/terraform/context_plugins.go | 62 ++++++++++++ ...onents_test.go => context_plugins_test.go} | 13 +-- internal/terraform/context_validate.go | 10 +- internal/terraform/context_validate_test.go | 8 +- internal/terraform/eval_context_builtin.go | 6 +- .../terraform/eval_context_builtin_test.go | 8 +- internal/terraform/graph_builder_apply.go | 4 +- .../terraform/graph_builder_apply_test.go | 94 +++++++++---------- .../terraform/graph_builder_destroy_plan.go | 4 +- internal/terraform/graph_builder_eval.go | 4 +- internal/terraform/graph_builder_import.go | 5 +- internal/terraform/graph_builder_plan.go | 4 +- internal/terraform/graph_builder_plan_test.go | 56 +++++------ internal/terraform/graph_walk_context.go | 2 +- internal/terraform/schemas.go | 16 ++-- .../terraform/transform_destroy_cbd_test.go | 10 +- 23 files changed, 194 insertions(+), 189 deletions(-) delete mode 100644 internal/terraform/context_components.go create mode 100644 internal/terraform/context_plugins.go rename internal/terraform/{context_components_test.go => context_plugins_test.go} (87%) diff --git a/internal/command/import_test.go b/internal/command/import_test.go index bb56751e72..1469ea81d2 100644 --- a/internal/command/import_test.go +++ b/internal/command/import_test.go @@ -332,7 +332,7 @@ func TestImport_initializationErrorShouldUnlock(t *testing.T) { // specifically, it should fail due to a missing provider msg := strings.ReplaceAll(ui.ErrorWriter.String(), "\n", " ") - if want := `unknown provider "registry.terraform.io/hashicorp/unknown"`; !strings.Contains(msg, want) { + if want := `unavailable provider "registry.terraform.io/hashicorp/unknown"`; !strings.Contains(msg, want) { t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg) } diff --git a/internal/terraform/context.go b/internal/terraform/context.go index 907b687623..e05200e1e5 100644 --- a/internal/terraform/context.go +++ b/internal/terraform/context.go @@ -88,7 +88,7 @@ type Context struct { // operations. meta *ContextMeta - components contextComponentFactory + plugins *contextPlugins dependencyLocks *depsfile.Locks providersInDevelopment map[addrs.Provider]struct{} @@ -144,10 +144,7 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) { par = 10 } - components := &basicComponentFactory{ - providers: opts.Providers, - provisioners: opts.Provisioners, - } + plugins := newContextPlugins(opts.Providers, opts.Provisioners) log.Printf("[TRACE] terraform.NewContext: complete") @@ -156,7 +153,7 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) { meta: opts.Meta, uiInput: opts.UIInput, - components: components, + plugins: plugins, dependencyLocks: opts.LockedDependencies, providersInDevelopment: opts.ProvidersInDevelopment, @@ -221,7 +218,7 @@ func (c *Context) Schemas(config *configs.Config, state *states.State) (*Schemas } } - ret, err := loadSchemas(config, state, c.components) + ret, err := loadSchemas(config, state, c.plugins) if err != nil { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, diff --git a/internal/terraform/context_apply.go b/internal/terraform/context_apply.go index 4ba7e8dc0e..4d5dc890f7 100644 --- a/internal/terraform/context_apply.go +++ b/internal/terraform/context_apply.go @@ -95,7 +95,7 @@ func (c *Context) applyGraph(plan *plans.Plan, config *configs.Config, schemas * Config: config, Changes: plan.Changes, State: plan.PriorState, - Components: c.components, + Plugins: c.plugins, Schemas: schemas, Targets: plan.TargetAddrs, ForceReplace: plan.ForceReplaceAddrs, diff --git a/internal/terraform/context_components.go b/internal/terraform/context_components.go deleted file mode 100644 index 66f5dc664b..0000000000 --- a/internal/terraform/context_components.go +++ /dev/null @@ -1,46 +0,0 @@ -package terraform - -import ( - "fmt" - - "github.com/hashicorp/terraform/internal/addrs" - "github.com/hashicorp/terraform/internal/providers" - "github.com/hashicorp/terraform/internal/provisioners" -) - -// contextComponentFactory is the interface that Context uses -// to initialize various components such as providers and provisioners. -// This factory gets more information than the raw maps using to initialize -// a Context. This information is used for debugging. -type contextComponentFactory interface { - // ResourceProvider creates a new ResourceProvider with the given type. - ResourceProvider(typ addrs.Provider) (providers.Interface, error) - - // ResourceProvisioner creates a new ResourceProvisioner with the given - // type. - ResourceProvisioner(typ string) (provisioners.Interface, error) -} - -// basicComponentFactory just calls a factory from a map directly. -type basicComponentFactory struct { - providers map[addrs.Provider]providers.Factory - provisioners map[string]provisioners.Factory -} - -func (c *basicComponentFactory) ResourceProvider(typ addrs.Provider) (providers.Interface, error) { - f, ok := c.providers[typ] - if !ok { - return nil, fmt.Errorf("unknown provider %q", typ.String()) - } - - return f() -} - -func (c *basicComponentFactory) ResourceProvisioner(typ string) (provisioners.Interface, error) { - f, ok := c.provisioners[typ] - if !ok { - return nil, fmt.Errorf("unknown provisioner %q", typ) - } - - return f() -} diff --git a/internal/terraform/context_eval.go b/internal/terraform/context_eval.go index 8be9b93678..ad3deeee1d 100644 --- a/internal/terraform/context_eval.go +++ b/internal/terraform/context_eval.go @@ -66,10 +66,10 @@ func (c *Context) Eval(config *configs.Config, state *states.State, moduleAddr a log.Printf("[DEBUG] Building and walking 'eval' graph") graph, moreDiags := (&EvalGraphBuilder{ - Config: config, - State: state, - Components: c.components, - Schemas: schemas, + Config: config, + State: state, + Plugins: c.plugins, + Schemas: schemas, }).Build(addrs.RootModuleInstance) diags = diags.Append(moreDiags) if moreDiags.HasErrors() { diff --git a/internal/terraform/context_import.go b/internal/terraform/context_import.go index 48a5858a3d..8675e06b5f 100644 --- a/internal/terraform/context_import.go +++ b/internal/terraform/context_import.go @@ -63,7 +63,7 @@ func (c *Context) Import(config *configs.Config, prevRunState *states.State, opt builder := &ImportGraphBuilder{ ImportTargets: opts.Targets, Config: config, - Components: c.components, + Plugins: c.plugins, Schemas: schemas, } diff --git a/internal/terraform/context_plan.go b/internal/terraform/context_plan.go index 7499e57d88..9f9170c8aa 100644 --- a/internal/terraform/context_plan.go +++ b/internal/terraform/context_plan.go @@ -371,7 +371,7 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State, graph, diags := (&PlanGraphBuilder{ Config: config, State: prevRunState, - Components: c.components, + Plugins: c.plugins, Schemas: schemas, Targets: opts.Targets, ForceReplace: opts.ForceReplace, @@ -383,7 +383,7 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State, graph, diags := (&PlanGraphBuilder{ Config: config, State: prevRunState, - Components: c.components, + Plugins: c.plugins, Schemas: schemas, Targets: opts.Targets, Validate: validate, @@ -395,7 +395,7 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State, graph, diags := (&DestroyPlanGraphBuilder{ Config: config, State: prevRunState, - Components: c.components, + Plugins: c.plugins, Schemas: schemas, Targets: opts.Targets, Validate: validate, diff --git a/internal/terraform/context_plugins.go b/internal/terraform/context_plugins.go new file mode 100644 index 0000000000..2bd1964d3a --- /dev/null +++ b/internal/terraform/context_plugins.go @@ -0,0 +1,62 @@ +package terraform + +import ( + "fmt" + "sync" + + "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/configs/configschema" + "github.com/hashicorp/terraform/internal/providers" + "github.com/hashicorp/terraform/internal/provisioners" +) + +// contextPlugins represents a library of available plugins (providers and +// provisioners) which we assume will all be used with the same +// terraform.Context, and thus it'll be safe to cache certain information +// about the providers for performance reasons. +type contextPlugins struct { + providerFactories map[addrs.Provider]providers.Factory + provisionerFactories map[string]provisioners.Factory + + // We memoize the schemas we've previously loaded in here, to avoid + // repeatedly paying the cost of activating the same plugins to access + // their schemas in various different spots. We use schemas for many + // purposes in Terraform, so there isn't a single choke point where + // it makes sense to preload all of them. + providerSchemas map[addrs.Provider]*ProviderSchema + provisionerSchemas map[string]*configschema.Block + schemasLock *sync.Mutex +} + +func newContextPlugins(providerFactories map[addrs.Provider]providers.Factory, provisionerFactories map[string]provisioners.Factory) *contextPlugins { + ret := &contextPlugins{ + providerFactories: providerFactories, + provisionerFactories: provisionerFactories, + } + ret.init() + return ret +} + +func (cp *contextPlugins) init() { + cp.providerSchemas = make(map[addrs.Provider]*ProviderSchema, len(cp.providerFactories)) + cp.provisionerSchemas = make(map[string]*configschema.Block, len(cp.provisionerFactories)) +} + +func (cp *contextPlugins) NewProviderInstance(addr addrs.Provider) (providers.Interface, error) { + f, ok := cp.providerFactories[addr] + if !ok { + return nil, fmt.Errorf("unavailable provider %q", addr.String()) + } + + return f() + +} + +func (cp *contextPlugins) NewProvisionerInstance(typ string) (provisioners.Interface, error) { + f, ok := cp.provisionerFactories[typ] + if !ok { + return nil, fmt.Errorf("unavailable provisioner %q", typ) + } + + return f() +} diff --git a/internal/terraform/context_components_test.go b/internal/terraform/context_plugins_test.go similarity index 87% rename from internal/terraform/context_components_test.go rename to internal/terraform/context_plugins_test.go index f92b41b6ac..130de5b522 100644 --- a/internal/terraform/context_components_test.go +++ b/internal/terraform/context_plugins_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform/internal/provisioners" ) -// simpleMockComponentFactory returns a component factory pre-configured with +// simpleMockPluginLibrary returns a plugin library pre-configured with // one provider and one provisioner, both called "test". // // The provider is built with simpleMockProvider and the provisioner with @@ -19,26 +19,27 @@ import ( // Each call to this function produces an entirely-separate set of objects, // so the caller can feel free to modify the returned value to further // customize the mocks contained within. -func simpleMockComponentFactory() *basicComponentFactory { +func simpleMockPluginLibrary() *contextPlugins { // We create these out here, rather than in the factory functions below, // because we want each call to the factory to return the _same_ instance, // so that test code can customize it before passing this component // factory into real code under test. provider := simpleMockProvider() provisioner := simpleMockProvisioner() - return &basicComponentFactory{ - providers: map[addrs.Provider]providers.Factory{ + ret := &contextPlugins{ + providerFactories: map[addrs.Provider]providers.Factory{ addrs.NewDefaultProvider("test"): func() (providers.Interface, error) { return provider, nil }, }, - provisioners: map[string]provisioners.Factory{ + provisionerFactories: map[string]provisioners.Factory{ "test": func() (provisioners.Interface, error) { return provisioner, nil }, }, } - + ret.init() // prepare the internal cache data structures + return ret } // simpleTestSchema returns a block schema that contains a few optional diff --git a/internal/terraform/context_validate.go b/internal/terraform/context_validate.go index bda38633ab..f951278952 100644 --- a/internal/terraform/context_validate.go +++ b/internal/terraform/context_validate.go @@ -44,11 +44,11 @@ func (c *Context) Validate(config *configs.Config) tfdiags.Diagnostics { log.Printf("[DEBUG] Building and walking validate graph") graph, moreDiags := ValidateGraphBuilder(&PlanGraphBuilder{ - Config: config, - Components: c.components, - Schemas: schemas, - Validate: true, - State: states.NewState(), + Config: config, + Plugins: c.plugins, + Schemas: schemas, + Validate: true, + State: states.NewState(), }).Build(addrs.RootModuleInstance) diags = diags.Append(moreDiags) if moreDiags.HasErrors() { diff --git a/internal/terraform/context_validate_test.go b/internal/terraform/context_validate_test.go index b25bed35e9..e4eee13b43 100644 --- a/internal/terraform/context_validate_test.go +++ b/internal/terraform/context_validate_test.go @@ -1198,10 +1198,10 @@ func TestContext2Validate_PlanGraphBuilder(t *testing.T) { assertNoDiagnostics(t, diags) graph, diags := ValidateGraphBuilder(&PlanGraphBuilder{ - Config: fixture.Config, - State: states.NewState(), - Components: c.components, - Schemas: schemas, + Config: fixture.Config, + State: states.NewState(), + Plugins: c.plugins, + Schemas: schemas, }).Build(addrs.RootModuleInstance) if diags.HasErrors() { t.Fatalf("errors from PlanGraphBuilder: %s", diags.Err()) diff --git a/internal/terraform/eval_context_builtin.go b/internal/terraform/eval_context_builtin.go index 1b971fd6b1..6bcf916630 100644 --- a/internal/terraform/eval_context_builtin.go +++ b/internal/terraform/eval_context_builtin.go @@ -62,7 +62,7 @@ type BuiltinEvalContext struct { VariableValues map[string]map[string]cty.Value VariableValuesLock *sync.Mutex - Components contextComponentFactory + Plugins *contextPlugins Hooks []Hook InputValue UIInput ProviderCache map[string]providers.Interface @@ -134,7 +134,7 @@ func (ctx *BuiltinEvalContext) InitProvider(addr addrs.AbsProviderConfig) (provi key := addr.String() - p, err := ctx.Components.ResourceProvider(addr.Provider) + p, err := ctx.Plugins.NewProviderInstance(addr.Provider) if err != nil { return nil, err } @@ -238,7 +238,7 @@ func (ctx *BuiltinEvalContext) Provisioner(n string) (provisioners.Interface, er p, ok := ctx.ProvisionerCache[n] if !ok { var err error - p, err = ctx.Components.ResourceProvisioner(n) + p, err = ctx.Plugins.NewProvisionerInstance(n) if err != nil { return nil, err } diff --git a/internal/terraform/eval_context_builtin_test.go b/internal/terraform/eval_context_builtin_test.go index 0521930b58..0db0096a75 100644 --- a/internal/terraform/eval_context_builtin_test.go +++ b/internal/terraform/eval_context_builtin_test.go @@ -59,11 +59,9 @@ func TestBuildingEvalContextInitProvider(t *testing.T) { ctx = ctx.WithPath(addrs.RootModuleInstance).(*BuiltinEvalContext) ctx.ProviderLock = &lock ctx.ProviderCache = make(map[string]providers.Interface) - ctx.Components = &basicComponentFactory{ - providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("test"): providers.FactoryFixed(testP), - }, - } + ctx.Plugins = newContextPlugins(map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): providers.FactoryFixed(testP), + }, nil) providerAddrDefault := addrs.AbsProviderConfig{ Module: addrs.RootModule, diff --git a/internal/terraform/graph_builder_apply.go b/internal/terraform/graph_builder_apply.go index bf213d1d06..ca8e5777fa 100644 --- a/internal/terraform/graph_builder_apply.go +++ b/internal/terraform/graph_builder_apply.go @@ -26,9 +26,9 @@ type ApplyGraphBuilder struct { // State is the current state State *states.State - // Components is a factory for the plug-in components (providers and + // Plugins is a library of the plug-in components (providers and // provisioners) available for use. - Components contextComponentFactory + Plugins *contextPlugins // Schemas is the repository of schemas we will draw from to analyse // the configuration. diff --git a/internal/terraform/graph_builder_apply_test.go b/internal/terraform/graph_builder_apply_test.go index b96149bac6..9aaa1650d8 100644 --- a/internal/terraform/graph_builder_apply_test.go +++ b/internal/terraform/graph_builder_apply_test.go @@ -46,10 +46,10 @@ func TestApplyGraphBuilder(t *testing.T) { } b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-basic"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), + Config: testModule(t, "graph-builder-apply-basic"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), } g, err := b.Build(addrs.RootModuleInstance) @@ -110,11 +110,11 @@ func TestApplyGraphBuilder_depCbd(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-dep-cbd"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), - State: state, + Config: testModule(t, "graph-builder-apply-dep-cbd"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), + State: state, } g, err := b.Build(addrs.RootModuleInstance) @@ -184,10 +184,10 @@ func TestApplyGraphBuilder_doubleCBD(t *testing.T) { } b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-double-cbd"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), + Config: testModule(t, "graph-builder-apply-double-cbd"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), } g, err := b.Build(addrs.RootModuleInstance) @@ -278,11 +278,11 @@ func TestApplyGraphBuilder_destroyStateOnly(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "empty"), - Changes: changes, - State: state, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), + Config: testModule(t, "empty"), + Changes: changes, + State: state, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), } g, diags := b.Build(addrs.RootModuleInstance) @@ -341,11 +341,11 @@ func TestApplyGraphBuilder_destroyCount(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-count"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), - State: state, + Config: testModule(t, "graph-builder-apply-count"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), + State: state, } g, err := b.Build(addrs.RootModuleInstance) @@ -404,11 +404,11 @@ func TestApplyGraphBuilder_moduleDestroy(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-module-destroy"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), - State: state, + Config: testModule(t, "graph-builder-apply-module-destroy"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), + State: state, } g, err := b.Build(addrs.RootModuleInstance) @@ -442,10 +442,10 @@ func TestApplyGraphBuilder_targetModule(t *testing.T) { } b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-target-module"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), + Config: testModule(t, "graph-builder-apply-target-module"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), Targets: []addrs.Targetable{ addrs.RootModuleInstance.Child("child2", addrs.NoKey), }, @@ -539,11 +539,11 @@ func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-orphan-update"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: schemas, - State: state, + Config: testModule(t, "graph-builder-apply-orphan-update"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: schemas, + State: state, } g, err := b.Build(addrs.RootModuleInstance) @@ -640,11 +640,11 @@ func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-apply-orphan-update"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: schemas, - State: state, + Config: testModule(t, "graph-builder-apply-orphan-update"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: schemas, + State: state, } g, err := b.Build(addrs.RootModuleInstance) @@ -691,11 +691,11 @@ func TestApplyGraphBuilder_orphanedWithProvider(t *testing.T) { ) b := &ApplyGraphBuilder{ - Config: testModule(t, "graph-builder-orphan-alias"), - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), - State: state, + Config: testModule(t, "graph-builder-orphan-alias"), + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), + State: state, } g, err := b.Build(addrs.RootModuleInstance) diff --git a/internal/terraform/graph_builder_destroy_plan.go b/internal/terraform/graph_builder_destroy_plan.go index 1973237b4b..55bae82fdd 100644 --- a/internal/terraform/graph_builder_destroy_plan.go +++ b/internal/terraform/graph_builder_destroy_plan.go @@ -23,9 +23,9 @@ type DestroyPlanGraphBuilder struct { // State is the current state State *states.State - // Components is a factory for the plug-in components (providers and + // Plugins is a library of plug-in components (providers and // provisioners) available for use. - Components contextComponentFactory + Plugins *contextPlugins // Schemas is the repository of schemas we will draw from to analyse // the configuration. diff --git a/internal/terraform/graph_builder_eval.go b/internal/terraform/graph_builder_eval.go index 65e6635506..f413dd7fea 100644 --- a/internal/terraform/graph_builder_eval.go +++ b/internal/terraform/graph_builder_eval.go @@ -30,9 +30,9 @@ type EvalGraphBuilder struct { // State is the current state State *states.State - // Components is a factory for the plug-in components (providers and + // Plugins is a library of plug-in components (providers and // provisioners) available for use. - Components contextComponentFactory + Plugins *contextPlugins // Schemas is the repository of schemas we will draw from to analyse // the configuration. diff --git a/internal/terraform/graph_builder_import.go b/internal/terraform/graph_builder_import.go index bbef67713f..d502b131ec 100644 --- a/internal/terraform/graph_builder_import.go +++ b/internal/terraform/graph_builder_import.go @@ -17,8 +17,9 @@ type ImportGraphBuilder struct { // Module is a configuration to build the graph from. See ImportOpts.Config. Config *configs.Config - // Components is the factory for our available plugin components. - Components contextComponentFactory + // Plugins is a library of plug-in components (providers and + // provisioners) available for use. + Plugins *contextPlugins // Schemas is the repository of schemas we will draw from to analyse // the configuration. diff --git a/internal/terraform/graph_builder_plan.go b/internal/terraform/graph_builder_plan.go index 8d68016249..e0a355d47f 100644 --- a/internal/terraform/graph_builder_plan.go +++ b/internal/terraform/graph_builder_plan.go @@ -28,9 +28,9 @@ type PlanGraphBuilder struct { // State is the current state State *states.State - // Components is a factory for the plug-in components (providers and + // Plugins is a library of plug-in components (providers and // provisioners) available for use. - Components contextComponentFactory + Plugins *contextPlugins // Schemas is the repository of schemas we will draw from to analyse // the configuration. diff --git a/internal/terraform/graph_builder_plan_test.go b/internal/terraform/graph_builder_plan_test.go index 6225e192e6..c5aa9a4559 100644 --- a/internal/terraform/graph_builder_plan_test.go +++ b/internal/terraform/graph_builder_plan_test.go @@ -26,16 +26,14 @@ func TestPlanGraphBuilder(t *testing.T) { }, } openstackProvider := mockProviderWithResourceTypeSchema("openstack_floating_ip", simpleTestSchema()) - components := &basicComponentFactory{ - providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("aws"): providers.FactoryFixed(awsProvider), - addrs.NewDefaultProvider("openstack"): providers.FactoryFixed(openstackProvider), - }, - } + plugins := newContextPlugins(map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("aws"): providers.FactoryFixed(awsProvider), + addrs.NewDefaultProvider("openstack"): providers.FactoryFixed(openstackProvider), + }, nil) b := &PlanGraphBuilder{ - Config: testModule(t, "graph-builder-plan-basic"), - Components: components, + Config: testModule(t, "graph-builder-plan-basic"), + Plugins: plugins, Schemas: &Schemas{ Providers: map[addrs.Provider]*ProviderSchema{ addrs.NewDefaultProvider("aws"): awsProvider.ProviderSchema(), @@ -77,15 +75,13 @@ func TestPlanGraphBuilder_dynamicBlock(t *testing.T) { }, }, }) - components := &basicComponentFactory{ - providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("test"): providers.FactoryFixed(provider), - }, - } + plugins := newContextPlugins(map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): providers.FactoryFixed(provider), + }, nil) b := &PlanGraphBuilder{ - Config: testModule(t, "graph-builder-plan-dynblock"), - Components: components, + Config: testModule(t, "graph-builder-plan-dynblock"), + Plugins: plugins, Schemas: &Schemas{ Providers: map[addrs.Provider]*ProviderSchema{ addrs.NewDefaultProvider("test"): provider.ProviderSchema(), @@ -142,15 +138,13 @@ func TestPlanGraphBuilder_attrAsBlocks(t *testing.T) { }, }, }) - components := &basicComponentFactory{ - providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("test"): providers.FactoryFixed(provider), - }, - } + plugins := newContextPlugins(map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): providers.FactoryFixed(provider), + }, nil) b := &PlanGraphBuilder{ - Config: testModule(t, "graph-builder-plan-attr-as-blocks"), - Components: components, + Config: testModule(t, "graph-builder-plan-attr-as-blocks"), + Plugins: plugins, Schemas: &Schemas{ Providers: map[addrs.Provider]*ProviderSchema{ addrs.NewDefaultProvider("test"): provider.ProviderSchema(), @@ -194,9 +188,9 @@ test_thing.b (expand) func TestPlanGraphBuilder_targetModule(t *testing.T) { b := &PlanGraphBuilder{ - Config: testModule(t, "graph-builder-plan-target-module-provider"), - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), + Config: testModule(t, "graph-builder-plan-target-module-provider"), + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), Targets: []addrs.Targetable{ addrs.RootModuleInstance.Child("child2", addrs.NoKey), }, @@ -216,15 +210,13 @@ func TestPlanGraphBuilder_targetModule(t *testing.T) { func TestPlanGraphBuilder_forEach(t *testing.T) { awsProvider := mockProviderWithResourceTypeSchema("aws_instance", simpleTestSchema()) - components := &basicComponentFactory{ - providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("aws"): providers.FactoryFixed(awsProvider), - }, - } + plugins := newContextPlugins(map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("aws"): providers.FactoryFixed(awsProvider), + }, nil) b := &PlanGraphBuilder{ - Config: testModule(t, "plan-for-each"), - Components: components, + Config: testModule(t, "plan-for-each"), + Plugins: plugins, Schemas: &Schemas{ Providers: map[addrs.Provider]*ProviderSchema{ addrs.NewDefaultProvider("aws"): awsProvider.ProviderSchema(), diff --git a/internal/terraform/graph_walk_context.go b/internal/terraform/graph_walk_context.go index 164a2ba2a5..3561ab983b 100644 --- a/internal/terraform/graph_walk_context.go +++ b/internal/terraform/graph_walk_context.go @@ -91,7 +91,7 @@ func (w *ContextGraphWalker) EvalContext() EvalContext { Hooks: w.Context.hooks, InputValue: w.Context.uiInput, InstanceExpanderValue: w.InstanceExpander, - Components: w.Context.components, + Plugins: w.Context.plugins, Schemas: w.Schemas, MoveResultsValue: w.MoveResults, ProviderCache: w.providerCache, diff --git a/internal/terraform/schemas.go b/internal/terraform/schemas.go index 974cbb2eb4..7b7177dbd0 100644 --- a/internal/terraform/schemas.go +++ b/internal/terraform/schemas.go @@ -74,22 +74,22 @@ func (ss *Schemas) ProvisionerConfig(name string) *configschema.Block { // either misbehavior on the part of one of the providers or of the provider // protocol itself. When returned with errors, the returned schemas object is // still valid but may be incomplete. -func loadSchemas(config *configs.Config, state *states.State, components contextComponentFactory) (*Schemas, error) { +func loadSchemas(config *configs.Config, state *states.State, plugins *contextPlugins) (*Schemas, error) { schemas := &Schemas{ Providers: map[addrs.Provider]*ProviderSchema{}, Provisioners: map[string]*configschema.Block{}, } var diags tfdiags.Diagnostics - newDiags := loadProviderSchemas(schemas.Providers, config, state, components) + newDiags := loadProviderSchemas(schemas.Providers, config, state, plugins) diags = diags.Append(newDiags) - newDiags = loadProvisionerSchemas(schemas.Provisioners, config, components) + newDiags = loadProvisionerSchemas(schemas.Provisioners, config, plugins) diags = diags.Append(newDiags) return schemas, diags.Err() } -func loadProviderSchemas(schemas map[addrs.Provider]*ProviderSchema, config *configs.Config, state *states.State, components contextComponentFactory) tfdiags.Diagnostics { +func loadProviderSchemas(schemas map[addrs.Provider]*ProviderSchema, config *configs.Config, state *states.State, plugins *contextPlugins) tfdiags.Diagnostics { var diags tfdiags.Diagnostics ensure := func(fqn addrs.Provider) { @@ -100,7 +100,7 @@ func loadProviderSchemas(schemas map[addrs.Provider]*ProviderSchema, config *con } log.Printf("[TRACE] LoadSchemas: retrieving schema for provider type %q", name) - provider, err := components.ResourceProvider(fqn) + provider, err := plugins.NewProviderInstance(fqn) if err != nil { // We'll put a stub in the map so we won't re-attempt this on // future calls. @@ -191,7 +191,7 @@ func loadProviderSchemas(schemas map[addrs.Provider]*ProviderSchema, config *con return diags } -func loadProvisionerSchemas(schemas map[string]*configschema.Block, config *configs.Config, components contextComponentFactory) tfdiags.Diagnostics { +func loadProvisionerSchemas(schemas map[string]*configschema.Block, config *configs.Config, plugins *contextPlugins) tfdiags.Diagnostics { var diags tfdiags.Diagnostics ensure := func(name string) { @@ -200,7 +200,7 @@ func loadProvisionerSchemas(schemas map[string]*configschema.Block, config *conf } log.Printf("[TRACE] LoadSchemas: retrieving schema for provisioner %q", name) - provisioner, err := components.ResourceProvisioner(name) + provisioner, err := plugins.NewProvisionerInstance(name) if err != nil { // We'll put a stub in the map so we won't re-attempt this on // future calls. @@ -237,7 +237,7 @@ func loadProvisionerSchemas(schemas map[string]*configschema.Block, config *conf // Must also visit our child modules, recursively. for _, cc := range config.Children { - childDiags := loadProvisionerSchemas(schemas, cc, components) + childDiags := loadProvisionerSchemas(schemas, cc, plugins) diags = diags.Append(childDiags) } } diff --git a/internal/terraform/transform_destroy_cbd_test.go b/internal/terraform/transform_destroy_cbd_test.go index 4e4409623d..a66243f540 100644 --- a/internal/terraform/transform_destroy_cbd_test.go +++ b/internal/terraform/transform_destroy_cbd_test.go @@ -14,11 +14,11 @@ func cbdTestGraph(t *testing.T, mod string, changes *plans.Changes, state *state module := testModule(t, mod) applyBuilder := &ApplyGraphBuilder{ - Config: module, - Changes: changes, - Components: simpleMockComponentFactory(), - Schemas: simpleTestSchemas(), - State: state, + Config: module, + Changes: changes, + Plugins: simpleMockPluginLibrary(), + Schemas: simpleTestSchemas(), + State: state, } g, err := (&BasicGraphBuilder{ Steps: cbdTestSteps(applyBuilder.Steps()),