2017-01-19 05:47:56 +01:00
|
|
|
package local
|
|
|
|
|
|
|
|
import (
|
2018-02-23 02:43:21 +01:00
|
|
|
"context"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
"fmt"
|
2018-10-17 23:05:57 +02:00
|
|
|
"log"
|
2019-10-08 21:08:27 +02:00
|
|
|
"sort"
|
2017-11-22 00:08:00 +01:00
|
|
|
|
2017-01-19 05:47:56 +01:00
|
|
|
"github.com/hashicorp/errwrap"
|
2021-05-17 17:42:17 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/backend"
|
2021-05-17 21:17:09 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/configs"
|
|
|
|
"github.com/hashicorp/terraform/internal/configs/configload"
|
2021-05-17 21:33:17 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/plans/planfile"
|
2021-05-17 21:43:35 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/states/statemgr"
|
2021-05-17 21:46:19 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/terraform"
|
2021-05-17 19:11:06 +02:00
|
|
|
"github.com/hashicorp/terraform/internal/tfdiags"
|
2018-12-01 00:15:28 +01:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
2017-01-19 05:47:56 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// backend.Local implementation.
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
func (b *Local) Context(op *backend.Operation) (*terraform.Context, statemgr.Full, tfdiags.Diagnostics) {
|
2017-01-19 05:47:56 +01:00
|
|
|
// Make sure the type is invalid. We use this as a way to know not
|
|
|
|
// to ask for input/validate.
|
|
|
|
op.Type = backend.OperationTypeInvalid
|
|
|
|
|
2021-02-16 13:19:22 +01:00
|
|
|
op.StateLocker = op.StateLocker.WithContext(context.Background())
|
2018-02-23 02:43:21 +01:00
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
ctx, _, stateMgr, diags := b.context(op)
|
|
|
|
return ctx, stateMgr, diags
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
func (b *Local) context(op *backend.Operation) (*terraform.Context, *configload.Snapshot, statemgr.Full, tfdiags.Diagnostics) {
|
2018-03-21 02:43:02 +01:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
// Get the latest state.
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: requesting state manager for workspace %q", op.Workspace)
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
s, err := b.StateMgr(op.Workspace)
|
2017-01-19 05:47:56 +01:00
|
|
|
if err != nil {
|
2018-03-21 02:43:02 +01:00
|
|
|
diags = diags.Append(errwrap.Wrapf("Error loading state: {{err}}", err))
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
return nil, nil, nil, diags
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: requesting state lock for workspace %q", op.Workspace)
|
2021-02-16 13:19:22 +01:00
|
|
|
if diags := op.StateLocker.Lock(s, op.Type.String()); diags.HasErrors() {
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
return nil, nil, nil, diags
|
2018-02-23 02:43:21 +01:00
|
|
|
}
|
2020-08-11 17:23:42 +02:00
|
|
|
|
|
|
|
defer func() {
|
|
|
|
// If we're returning with errors, and thus not producing a valid
|
|
|
|
// context, we'll want to avoid leaving the workspace locked.
|
|
|
|
if diags.HasErrors() {
|
2021-02-16 13:19:22 +01:00
|
|
|
diags = diags.Append(op.StateLocker.Unlock())
|
2020-08-11 17:23:42 +02:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: reading remote state for workspace %q", op.Workspace)
|
2017-01-19 05:47:56 +01:00
|
|
|
if err := s.RefreshState(); err != nil {
|
2018-03-21 02:43:02 +01:00
|
|
|
diags = diags.Append(errwrap.Wrapf("Error loading state: {{err}}", err))
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
return nil, nil, nil, diags
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize our context options
|
|
|
|
var opts terraform.ContextOpts
|
|
|
|
if v := b.ContextOpts; v != nil {
|
|
|
|
opts = *v
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy set options from the operation
|
2021-04-06 01:28:59 +02:00
|
|
|
opts.PlanMode = op.PlanMode
|
2017-01-19 05:47:56 +01:00
|
|
|
opts.Targets = op.Targets
|
2021-04-07 02:37:38 +02:00
|
|
|
opts.ForceReplace = op.ForceReplace
|
2017-01-19 05:47:56 +01:00
|
|
|
opts.UIInput = op.UIIn
|
2021-02-12 02:52:10 +01:00
|
|
|
opts.Hooks = op.Hooks
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 19:33:53 +02:00
|
|
|
|
2020-12-10 15:44:22 +01:00
|
|
|
opts.SkipRefresh = op.Type != backend.OperationTypeRefresh && !op.PlanRefresh
|
2020-09-23 17:09:42 +02:00
|
|
|
if opts.SkipRefresh {
|
|
|
|
log.Printf("[DEBUG] backend/local: skipping refresh of managed resources")
|
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
// Load the latest state. If we enter contextFromPlanFile below then the
|
|
|
|
// state snapshot in the plan file must match this, or else it'll return
|
|
|
|
// error diagnostics.
|
2018-11-26 14:06:27 +01:00
|
|
|
log.Printf("[TRACE] backend/local: retrieving local state snapshot for workspace %q", op.Workspace)
|
2017-01-19 05:47:56 +01:00
|
|
|
opts.State = s.State()
|
|
|
|
|
|
|
|
var tfCtx *terraform.Context
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 19:33:53 +02:00
|
|
|
var ctxDiags tfdiags.Diagnostics
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
var configSnap *configload.Snapshot
|
|
|
|
if op.PlanFile != nil {
|
2018-10-11 19:22:10 +02:00
|
|
|
var stateMeta *statemgr.SnapshotMeta
|
|
|
|
// If the statemgr implements our optional PersistentMeta interface then we'll
|
|
|
|
// additionally verify that the state snapshot in the plan file has
|
|
|
|
// consistent metadata, as an additional safety check.
|
|
|
|
if sm, ok := s.(statemgr.PersistentMeta); ok {
|
|
|
|
m := sm.StateSnapshotMeta()
|
|
|
|
stateMeta = &m
|
|
|
|
}
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: building context from plan file")
|
2018-10-11 19:22:10 +02:00
|
|
|
tfCtx, configSnap, ctxDiags = b.contextFromPlanFile(op.PlanFile, opts, stateMeta)
|
2021-02-25 15:53:57 +01:00
|
|
|
if ctxDiags.HasErrors() {
|
2021-05-26 22:05:58 +02:00
|
|
|
diags = diags.Append(ctxDiags)
|
|
|
|
return nil, nil, nil, diags
|
2021-02-25 15:53:57 +01:00
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
// Write sources into the cache of the main loader so that they are
|
|
|
|
// available if we need to generate diagnostic message snippets.
|
|
|
|
op.ConfigLoader.ImportSourcesFromSnapshot(configSnap)
|
2017-01-19 05:47:56 +01:00
|
|
|
} else {
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: building context for current working directory")
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
tfCtx, configSnap, ctxDiags = b.contextDirect(op, opts)
|
2017-06-22 19:15:30 +02:00
|
|
|
}
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 19:33:53 +02:00
|
|
|
diags = diags.Append(ctxDiags)
|
2018-08-25 01:51:57 +02:00
|
|
|
if diags.HasErrors() {
|
|
|
|
return nil, nil, nil, diags
|
|
|
|
}
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: finished building terraform.Context")
|
2017-01-19 05:47:56 +01:00
|
|
|
|
|
|
|
// If we have an operation, then we automatically do the input/validate
|
|
|
|
// here since every option requires this.
|
|
|
|
if op.Type != backend.OperationTypeInvalid {
|
|
|
|
// If input asking is enabled, then do that
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
if op.PlanFile == nil && b.OpInput {
|
2017-01-19 05:47:56 +01:00
|
|
|
mode := terraform.InputModeProvider
|
|
|
|
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: requesting interactive input, if necessary")
|
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 19:33:53 +02:00
|
|
|
inputDiags := tfCtx.Input(mode)
|
|
|
|
diags = diags.Append(inputDiags)
|
|
|
|
if inputDiags.HasErrors() {
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
return nil, nil, nil, diags
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If validation is enabled, validate
|
|
|
|
if b.OpValidation {
|
2018-10-12 01:36:09 +02:00
|
|
|
log.Printf("[TRACE] backend/local: running validation operation")
|
2020-08-31 21:45:39 +02:00
|
|
|
validateDiags := tfCtx.Validate()
|
2018-03-21 02:43:02 +01:00
|
|
|
diags = diags.Append(validateDiags)
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
return tfCtx, configSnap, s, diags
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Local) contextDirect(op *backend.Operation, opts terraform.ContextOpts) (*terraform.Context, *configload.Snapshot, tfdiags.Diagnostics) {
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
|
|
|
|
// Load the configuration using the caller-provided configuration loader.
|
|
|
|
config, configSnap, configDiags := op.ConfigLoader.LoadConfigWithSnapshot(op.ConfigDir)
|
|
|
|
diags = diags.Append(configDiags)
|
|
|
|
if configDiags.HasErrors() {
|
|
|
|
return nil, nil, diags
|
|
|
|
}
|
|
|
|
opts.Config = config
|
|
|
|
|
2019-10-09 23:29:40 +02:00
|
|
|
var rawVariables map[string]backend.UnparsedVariableValue
|
|
|
|
if op.AllowUnsetVariables {
|
|
|
|
// Rather than prompting for input, we'll just stub out the required
|
|
|
|
// but unset variables with unknown values to represent that they are
|
|
|
|
// placeholders for values the user would need to provide for other
|
|
|
|
// operations.
|
|
|
|
rawVariables = b.stubUnsetRequiredVariables(op.Variables, config.Module.Variables)
|
|
|
|
} else {
|
|
|
|
// If interactive input is enabled, we might gather some more variable
|
|
|
|
// values through interactive prompts.
|
|
|
|
// TODO: Need to route the operation context through into here, so that
|
|
|
|
// the interactive prompts can be sensitive to its timeouts/etc.
|
|
|
|
rawVariables = b.interactiveCollectVariables(context.TODO(), op.Variables, config.Module.Variables, opts.UIInput)
|
|
|
|
}
|
2019-10-08 21:08:27 +02:00
|
|
|
|
|
|
|
variables, varDiags := backend.ParseVariableValues(rawVariables, config.Module.Variables)
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
diags = diags.Append(varDiags)
|
|
|
|
if diags.HasErrors() {
|
|
|
|
return nil, nil, diags
|
|
|
|
}
|
2019-10-08 21:08:27 +02:00
|
|
|
opts.Variables = variables
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
|
|
|
|
tfCtx, ctxDiags := terraform.NewContext(&opts)
|
|
|
|
diags = diags.Append(ctxDiags)
|
|
|
|
return tfCtx, configSnap, diags
|
|
|
|
}
|
|
|
|
|
2018-10-11 19:22:10 +02:00
|
|
|
func (b *Local) contextFromPlanFile(pf *planfile.Reader, opts terraform.ContextOpts, currentStateMeta *statemgr.SnapshotMeta) (*terraform.Context, *configload.Snapshot, tfdiags.Diagnostics) {
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
|
|
|
|
const errSummary = "Invalid plan file"
|
|
|
|
|
|
|
|
// A plan file has a snapshot of configuration embedded inside it, which
|
|
|
|
// is used instead of whatever configuration might be already present
|
|
|
|
// in the filesystem.
|
|
|
|
snap, err := pf.ReadConfigSnapshot()
|
|
|
|
if err != nil {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
errSummary,
|
|
|
|
fmt.Sprintf("Failed to read configuration snapshot from plan file: %s.", err),
|
|
|
|
))
|
2018-10-11 19:22:10 +02:00
|
|
|
return nil, snap, diags
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
}
|
|
|
|
loader := configload.NewLoaderFromSnapshot(snap)
|
|
|
|
config, configDiags := loader.LoadConfig(snap.Modules[""].Dir)
|
|
|
|
diags = diags.Append(configDiags)
|
|
|
|
if configDiags.HasErrors() {
|
|
|
|
return nil, snap, diags
|
|
|
|
}
|
|
|
|
opts.Config = config
|
|
|
|
|
2018-10-11 19:22:10 +02:00
|
|
|
// A plan file also contains a snapshot of the prior state the changes
|
|
|
|
// are intended to apply to.
|
|
|
|
priorStateFile, err := pf.ReadStateFile()
|
|
|
|
if err != nil {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
errSummary,
|
|
|
|
fmt.Sprintf("Failed to read prior state snapshot from plan file: %s.", err),
|
|
|
|
))
|
|
|
|
return nil, snap, diags
|
|
|
|
}
|
|
|
|
if currentStateMeta != nil {
|
|
|
|
// If the caller sets this, we require that the stored prior state
|
|
|
|
// has the same metadata, which is an extra safety check that nothing
|
|
|
|
// has changed since the plan was created. (All of the "real-world"
|
2020-09-03 10:25:55 +02:00
|
|
|
// state manager implementations support this, but simpler test backends
|
2018-10-11 19:22:10 +02:00
|
|
|
// may not.)
|
2018-10-13 03:04:26 +02:00
|
|
|
if currentStateMeta.Lineage != "" && priorStateFile.Lineage != "" {
|
|
|
|
if priorStateFile.Serial != currentStateMeta.Serial || priorStateFile.Lineage != currentStateMeta.Lineage {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Saved plan is stale",
|
|
|
|
"The given plan file can no longer be applied because the state was changed by another operation after the plan was created.",
|
|
|
|
))
|
|
|
|
}
|
2018-10-11 19:22:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// The caller already wrote the "current state" here, but we're overriding
|
|
|
|
// it here with the prior state. These two should actually be identical in
|
|
|
|
// normal use, particularly if we validated the state meta above, but
|
|
|
|
// we do this here anyway to ensure consistent behavior.
|
|
|
|
opts.State = priorStateFile.State
|
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
plan, err := pf.ReadPlan()
|
|
|
|
if err != nil {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
errSummary,
|
|
|
|
fmt.Sprintf("Failed to read plan from plan file: %s.", err),
|
|
|
|
))
|
2018-09-30 18:29:51 +02:00
|
|
|
return nil, snap, diags
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
variables := terraform.InputValues{}
|
|
|
|
for name, dyVal := range plan.VariableValues {
|
2018-12-01 00:15:28 +01:00
|
|
|
val, err := dyVal.Decode(cty.DynamicPseudoType)
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
if err != nil {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
errSummary,
|
|
|
|
fmt.Sprintf("Invalid value for variable %q recorded in plan file: %s.", name, err),
|
|
|
|
))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
variables[name] = &terraform.InputValue{
|
|
|
|
Value: val,
|
|
|
|
SourceType: terraform.ValueFromPlan,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
opts.Variables = variables
|
2018-10-10 01:31:19 +02:00
|
|
|
opts.Changes = plan.Changes
|
2018-10-11 19:22:10 +02:00
|
|
|
opts.Targets = plan.TargetAddrs
|
2021-04-07 02:37:38 +02:00
|
|
|
opts.ForceReplace = plan.ForceReplaceAddrs
|
2018-10-11 19:22:10 +02:00
|
|
|
opts.ProviderSHA256s = plan.ProviderSHA256s
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
|
|
|
|
tfCtx, ctxDiags := terraform.NewContext(&opts)
|
|
|
|
diags = diags.Append(ctxDiags)
|
|
|
|
return tfCtx, snap, diags
|
2017-01-19 05:47:56 +01:00
|
|
|
}
|
2017-02-07 22:22:28 +01:00
|
|
|
|
2019-10-08 21:08:27 +02:00
|
|
|
// interactiveCollectVariables attempts to complete the given existing
|
|
|
|
// map of variables by interactively prompting for any variables that are
|
|
|
|
// declared as required but not yet present.
|
|
|
|
//
|
|
|
|
// If interactive input is disabled for this backend instance then this is
|
|
|
|
// a no-op. If input is enabled but fails for some reason, the resulting
|
|
|
|
// map will be incomplete. For these reasons, the caller must still validate
|
|
|
|
// that the result is complete and valid.
|
|
|
|
//
|
|
|
|
// This function does not modify the map given in "existing", but may return
|
|
|
|
// it unchanged if no modifications are required. If modifications are required,
|
|
|
|
// the result is a new map with all of the elements from "existing" plus
|
|
|
|
// additional elements as appropriate.
|
|
|
|
//
|
|
|
|
// Interactive prompting is a "best effort" thing for first-time user UX and
|
|
|
|
// not something we expect folks to be relying on for routine use. Terraform
|
|
|
|
// is primarily a non-interactive tool and so we prefer to report in error
|
|
|
|
// messages that variables are not set rather than reporting that input failed:
|
|
|
|
// the primary resolution to missing variables is to provide them by some other
|
|
|
|
// means.
|
|
|
|
func (b *Local) interactiveCollectVariables(ctx context.Context, existing map[string]backend.UnparsedVariableValue, vcs map[string]*configs.Variable, uiInput terraform.UIInput) map[string]backend.UnparsedVariableValue {
|
|
|
|
var needed []string
|
|
|
|
if b.OpInput && uiInput != nil {
|
|
|
|
for name, vc := range vcs {
|
|
|
|
if !vc.Required() {
|
|
|
|
continue // We only prompt for required variables
|
|
|
|
}
|
|
|
|
if _, exists := existing[name]; !exists {
|
|
|
|
needed = append(needed, name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Print("[DEBUG] backend/local: Skipping interactive prompts for variables because input is disabled")
|
|
|
|
}
|
|
|
|
if len(needed) == 0 {
|
|
|
|
return existing
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] backend/local: will prompt for input of unset required variables %s", needed)
|
|
|
|
|
|
|
|
// If we get here then we're planning to prompt for at least one additional
|
|
|
|
// variable's value.
|
|
|
|
sort.Strings(needed) // prompt in lexical order
|
|
|
|
ret := make(map[string]backend.UnparsedVariableValue, len(vcs))
|
|
|
|
for k, v := range existing {
|
|
|
|
ret[k] = v
|
|
|
|
}
|
|
|
|
for _, name := range needed {
|
|
|
|
vc := vcs[name]
|
|
|
|
rawValue, err := uiInput.Input(ctx, &terraform.InputOpts{
|
|
|
|
Id: fmt.Sprintf("var.%s", name),
|
|
|
|
Query: fmt.Sprintf("var.%s", name),
|
|
|
|
Description: vc.Description,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
// Since interactive prompts are best-effort, we'll just continue
|
|
|
|
// here and let subsequent validation report this as a variable
|
|
|
|
// not specified.
|
|
|
|
log.Printf("[WARN] backend/local: Failed to request user input for variable %q: %s", name, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
ret[name] = unparsedInteractiveVariableValue{Name: name, RawValue: rawValue}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2019-10-09 23:29:40 +02:00
|
|
|
// stubUnsetVariables ensures that all required variables defined in the
|
|
|
|
// configuration exist in the resulting map, by adding new elements as necessary.
|
|
|
|
//
|
|
|
|
// The stubbed value of any additions will be an unknown variable conforming
|
|
|
|
// to the variable's configured type constraint, meaning that no particular
|
|
|
|
// value is known and that one must be provided by the user in order to get
|
|
|
|
// a complete result.
|
|
|
|
//
|
|
|
|
// Unset optional attributes (those with default values) will not be populated
|
|
|
|
// by this function, under the assumption that a later step will handle those.
|
|
|
|
// In this sense, stubUnsetRequiredVariables is essentially a non-interactive,
|
|
|
|
// non-error-producing variant of interactiveCollectVariables that creates
|
|
|
|
// placeholders for values the user would be prompted for interactively on
|
|
|
|
// other operations.
|
|
|
|
//
|
|
|
|
// This function should be used only in situations where variables values
|
|
|
|
// will not be directly used and the variables map is being constructed only
|
|
|
|
// to produce a complete Terraform context for some ancillary functionality
|
|
|
|
// like "terraform console", "terraform state ...", etc.
|
|
|
|
//
|
|
|
|
// This function is guaranteed not to modify the given map, but it may return
|
|
|
|
// the given map unchanged if no additions are required. If additions are
|
|
|
|
// required then the result will be a new map containing everything in the
|
|
|
|
// given map plus additional elements.
|
|
|
|
func (b *Local) stubUnsetRequiredVariables(existing map[string]backend.UnparsedVariableValue, vcs map[string]*configs.Variable) map[string]backend.UnparsedVariableValue {
|
|
|
|
var missing bool // Do we need to add anything?
|
|
|
|
for name, vc := range vcs {
|
|
|
|
if !vc.Required() {
|
|
|
|
continue // We only stub required variables
|
|
|
|
}
|
|
|
|
if _, exists := existing[name]; !exists {
|
|
|
|
missing = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !missing {
|
|
|
|
return existing
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get down here then there's at least one variable value to add.
|
|
|
|
ret := make(map[string]backend.UnparsedVariableValue, len(vcs))
|
|
|
|
for k, v := range existing {
|
|
|
|
ret[k] = v
|
|
|
|
}
|
|
|
|
for name, vc := range vcs {
|
|
|
|
if !vc.Required() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if _, exists := existing[name]; !exists {
|
|
|
|
ret[name] = unparsedUnknownVariableValue{Name: name, WantType: vc.Type}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2019-10-08 21:08:27 +02:00
|
|
|
type unparsedInteractiveVariableValue struct {
|
|
|
|
Name, RawValue string
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ backend.UnparsedVariableValue = unparsedInteractiveVariableValue{}
|
|
|
|
|
|
|
|
func (v unparsedInteractiveVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
val, valDiags := mode.Parse(v.Name, v.RawValue)
|
|
|
|
diags = diags.Append(valDiags)
|
|
|
|
if diags.HasErrors() {
|
|
|
|
return nil, diags
|
|
|
|
}
|
|
|
|
return &terraform.InputValue{
|
|
|
|
Value: val,
|
|
|
|
SourceType: terraform.ValueFromInput,
|
|
|
|
}, diags
|
|
|
|
}
|
|
|
|
|
2019-10-09 23:29:40 +02:00
|
|
|
type unparsedUnknownVariableValue struct {
|
|
|
|
Name string
|
|
|
|
WantType cty.Type
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ backend.UnparsedVariableValue = unparsedUnknownVariableValue{}
|
|
|
|
|
|
|
|
func (v unparsedUnknownVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
|
|
|
|
return &terraform.InputValue{
|
|
|
|
Value: cty.UnknownVal(v.WantType),
|
|
|
|
SourceType: terraform.ValueFromInput,
|
|
|
|
}, nil
|
|
|
|
}
|