diff --git a/internal/stacks/stackruntime/internal/stackeval/component_instance.go b/internal/stacks/stackruntime/internal/stackeval/component_instance.go index 1926f32757..b214f11922 100644 --- a/internal/stacks/stackruntime/internal/stackeval/component_instance.go +++ b/internal/stacks/stackruntime/internal/stackeval/component_instance.go @@ -12,6 +12,8 @@ import ( "github.com/zclconf/go-cty/cty/convert" "github.com/hashicorp/terraform/internal/addrs" + fileProvisioner "github.com/hashicorp/terraform/internal/builtin/provisioners/file" + remoteExecProvisioner "github.com/hashicorp/terraform/internal/builtin/provisioners/remote-exec" "github.com/hashicorp/terraform/internal/collections" "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/instances" @@ -19,6 +21,7 @@ import ( "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/promising" "github.com/hashicorp/terraform/internal/providers" + "github.com/hashicorp/terraform/internal/provisioners" "github.com/hashicorp/terraform/internal/stacks/stackaddrs" "github.com/hashicorp/terraform/internal/stacks/stackconfig/stackconfigtypes" "github.com/hashicorp/terraform/internal/stacks/stackplan" @@ -490,6 +493,7 @@ func (c *ComponentInstance) CheckModuleTreePlan(ctx context.Context) (*plans.Pla }, }, PreloadedProviderSchemas: providerSchemas, + Provisioners: c.availableProvisioners(), }) if err != nil { // Should not get here because we should always pass a valid @@ -662,6 +666,7 @@ func (c *ComponentInstance) ApplyModuleTreePlan(ctx context.Context, plan *plans tfHook, }, PreloadedProviderSchemas: providerSchemas, + Provisioners: c.availableProvisioners(), }) if err != nil { // Should not get here because we should always pass a valid @@ -1301,6 +1306,35 @@ func (c *ComponentInstance) resourceTypeSchema(ctx context.Context, providerType return ret, nil } +// availableProvisioners returns the table of provisioner factories that should +// be made available to modules in this component. +func (c *ComponentInstance) availableProvisioners() map[string]provisioners.Factory { + return map[string]provisioners.Factory{ + "remote-exec": func() (provisioners.Interface, error) { + return remoteExecProvisioner.New(), nil + }, + "file": func() (provisioners.Interface, error) { + return fileProvisioner.New(), nil + }, + "local-exec": func() (provisioners.Interface, error) { + // We don't yet have any way to ensure a consistent execution + // environment for local-exec, which means that use of this + // provisioner is very likely to hurt portability between + // local and remote usage of stacks. Existing use of local-exec + // also tends to assume a writable module directory, whereas + // stack components execute from a read-only directory. + // + // Therefore we'll leave this unavailable for now with an explicit + // error message, although we might revisit this later if there's + // a strong reason to allow it and if we can find a suitable + // way to avoid the portability pitfalls that might inhibit + // moving execution of a stack from one execution environment to + // another. + return nil, fmt.Errorf("local-exec provisioners are not supported in stack components; use provider functionality or remote provisioners instead") + }, + } +} + func (c *ComponentInstance) tracingName() string { return c.Addr().String() }