Commit Graph

3338 Commits

Author SHA1 Message Date
Martin Atkins 0ee76b92b8 core: Update working state for resource instances in refresh-only mode
Previously in refresh-only mode we were skipping making any updates to the
working state at all. That's not correct, though: if the state upgrade or
refresh steps detected changes then we need to at least commit _those_ to
the working state, because those can then be detected by downstream
objects like output values.
2021-05-10 09:24:07 -07:00
Martin Atkins 8d4d333efe core: If we refresh during orphan processing, use the result for planning
If we don't do this then we can create a situation where refresh detects
that an object already doesn't exist but we plan to destroy it anyway,
rather than returning "no changes" as expected.
2021-05-06 13:26:37 -07:00
Martin Atkins 3443621227 core: Track both previous run state and refresh state during planning
The "previous run state" is our record of what the previous run of
Terraform considered to be its outcome, but in order to do anything useful
with that we must ensure that the data inside conforms to the current
resource type schemas, which might be different than the schemas that were
current during the previous run if the relevant provider has since been
upgraded.

For that reason then, we'll start off with the previous run state set
exactly equal to what was saved in the prior snapshot (modulo any changes
that happened during a state file format upgrade) but then during our
planning operation we'll overwrite individual resource instance objects
with the result of upgrading, so that in a situation where we successfully
run plan to completion the previous run state should always have a
compatible schema with the "prior state" (the result of refreshing) for
managed resources, and thus the caller can meaningfully compare the two
in order to detect and describe any out-of-band changes that occurred
since the previous run.
2021-05-05 15:11:05 -07:00
Martin Atkins 7c6e78bcb0 plans: Track both the previous run and prior states in the plan
Until now we've not really cared much about the state snapshot produced
by the previous Terraform operation, except to use it as a jumping-off
point for our refresh step.

However, we'd like to be able to report to an end-user whenever Terraform
detects a change that occurred outside of Terraform, because that's often
helpful context for understanding why a plan contains changes that don't
seem to have corresponding changes in the configuration.

As part of reporting that we'll need to keep track of the state as it
was before we did any refreshing work, so we can then compare that against
the state after refreshing. To retain enough data to achieve that, the
existing Plan field State is now two fields: PrevRunState and PriorState.

This also includes a very shallow change in the core package to make it
populate something somewhat-reasonable into this field so that integration
tests can function reasonably. However, this shallow implementation isn't
really sufficient for real-world use of PrevRunState because we'll
actually need to update PrevRunState as part of planning in order to
incorporate the results of any provider-specific state upgrades to make
the PrevRunState objects compatible with the current provider schema, or
else our diffs won't be valid. This deeper awareness of PrevRunState in
Terraform Core will follow in a subsequent commit, prior to anything else
making use of Plan.PrevRunState.
2021-05-05 15:11:05 -07:00
James Bardin 1e3a60c7ac
Merge pull request #28606 from hashicorp/jbardin/providers-in-modules
Validate passing default providers through modules
2021-05-05 09:07:02 -04:00
Martin Atkins c63c06d3c4 core: -replace to emit only one warning for incomplete address
If the user gives an index-less address for a resource that expects
instance keys then previously we would've emitted one error per declared
instance of the resource, which is overwhelming and not especially
helpful.

Instead, we'll deal with that check prior to expanding resources into
resource instances, and thus we can report a single error which talks
about all of the instances at once.

This does unfortunately come at the expense of splitting the logic for
dealing with the "force replace" addresses into two places, which will
likely make later maintenance harder. In an attempt to mitigate that,
I've included a comment in each place that mentions the other place, which
hopefully future maintainers will keep up-to-date if that situation
changes.
2021-05-03 15:43:23 -07:00
James Bardin f738246a03 add default provider nodes to root modules
If a root modules declares a required_provider but has no configuration,
add a graph node for the provider as if there were an empty
configuration. This will allow the provider to be referenced by name in
module call provider maps, so that a module can pass a default provider
by name to a submodule.

Normally these nodes are added by the MissingProviderTransformer, but
they need to be in place earlier to resolve any possible "proxy provider
nodes" within modules.
2021-05-03 16:27:08 -04:00
Martin Atkins 06adc69e2c plans: Plan.Mode is now Plan.UIMode
This is to make it more obvious at all uses of this field that it's not
something to be used for anything other than UI decisions, hopefully
prompting a reader of code elsewhere to refer to the comments to
understand why it has this unusual prefix and thus see what its intended
purpose is.
2021-04-30 10:30:56 -07:00
Martin Atkins b37b1beddd core: Minimal initial implementation of -replace=... option
This only includes the internal mechanisms to make it work, and not any
of the necessary UI changes to "terraform plan" and "terraform apply" to
activate it yet.

The force-replace options are ultimately handled inside the
NodeAbstractResourceInstance.plan method, at the same place we handle the
similar situation of the provider indicating that replacement is needed,
and so the rest of the changes here are just to propagate the settings
through all of the layers in order to reach that point.
2021-04-30 10:30:56 -07:00
Martin Atkins 1b464e1e9a core: Minimal initial implementation of "refresh only" planning mode
This only includes the core mechanisms to make it work. There's not yet
any way to turn this mode on as an end-user, because we have to do some
more work at the UI layer to present this well before we could include it
as an end-user-visible feature in a release.

At the lowest level of abstraction inside the graph nodes themselves, this
effectively mirrors the existing option to disable refreshing with a new
option to disable change-planning, so that either "half" of the process
can be disabled. As far as the nodes are concerned it would be possible
in principle to disable _both_, but the higher-level representation of
these modes prevents that combination from reaching Terraform Core in
practice, because we block using -refresh-only and -refresh=false at the
same time.
2021-04-30 10:30:56 -07:00
Martin Atkins b802237e03 plans: Track an optional extra "reason" for some planned actions
Previously we were repeating some logic in the UI layer in order to
recover relevant additional context about a change to report to a user.
In order to help keep things consistent, and to have a clearer path for
adding more such things in the future, here we capture this user-facing
idea of an "action reason" within the plan model, and then use that
directly in order to decide how to describe the change to the user.

For the moment the "tainted" situation is the only one that gets a special
message, matching what we had before, but we can expand on this in future
in order to give better feedback about the other replace situations too.

This also preemptively includes the "replacing by request" reason, which
is currently not reachable but will be used in the near future as part of
implementing the -replace=... plan command line option to allow forcing
a particular object to be replaced.

So far we don't have any special reasons for anything other than replacing,
which makes sense because replacing is the only one that is in a sense
a special case of another action (Update), but this could expand to
other kinds of reasons in the future, such as explaining which of the
few different reasons a data source read might be deferred until the
apply step.
2021-04-29 17:50:46 -07:00
James Bardin 479a091324
Merge pull request #28543 from hashicorp/jbardin/provider-diagnostics
Add more diagnostic configuration context to provider methods
2021-04-29 10:28:58 -04:00
James Bardin 7eade2cb52 add more diagnostics context
There were some remaining calls to provider where configuration could be
added to diagnostics, where warnings would not get config annotations,
or the diagnostics were skipped entirely.
2021-04-28 18:01:50 -04:00
Alisdair McDiarmid 4b1ff4eda7
Merge pull request #28523 from hashicorp/alisdair/json-plan-sensitive-provider-attrs
core: Add sensitive provider attrs to JSON plan
2021-04-28 15:49:47 -04:00
James Bardin 1db29d775e unmark planned data source values 2021-04-28 14:09:28 -04:00
James Bardin 0c8b4ce755 add context to UgpradeResourceState diags
This path was not yet using diagnostics, and returned simple errors.
2021-04-28 14:09:28 -04:00
Martin Atkins c6a7d080d9 core: Generalize the idea of a "plan mode", vs just destroy flag
Previously there were only two planning modes: normal mode and destroy
mode. In that context it made sense for these to be distinguished only by
a boolean flag.

We're now getting ready to add our third mode, "refresh only". This
establishes the idea that planning can be done in one of a number of
mutually-exclusive "modes", which are related to but separate from the
various other options that serve as modifiers for the plan operation.

This commit only introduces the new plans.Mode type and replaces the
existing "destroy" flag with a variable of that type. This doesn't cause
any change in effective behavior because Terraform Core still supports
only NormalMode and DestroyMode, with NewContext rejecting an attempt to
create a RefreshMode context for now.

It is in retrospect a little odd that the "destroy" flag was part of
ContextOpts rather than just an argument to the Plan method, but
refactoring that would be too invasive a change for right now so we'll
leave this as a field of the context for now and save revisiting that for
another day.
2021-04-27 08:23:54 -07:00
Alisdair McDiarmid c89004d223 core: Add sensitive provider attrs to JSON plan
When rendering a stored plan file as JSON, we include a data structure
representing the sensitivity of the changed resource values. Prior to
this commit, this was a direct representation of the sensitivity marks
applied to values via mechanisms such as sensitive variables, sensitive
outputs, and the `sensitive` function.

This commit extends this to include sensitivity based on the provider
schema. This is in line with the UI rendering of the plan, which
considers these two different types of sensitivity to be equivalent.

Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2021-04-27 10:29:34 -04:00
James Bardin 4997b9b5bb
Merge pull request #28424 from hashicorp/jbardin/dynamic
Better planing of unknown dynamic blocks
2021-04-23 18:26:21 -04:00
Alisdair McDiarmid 43bf3832d5 core: Loosen output value sensitivity requirement
Non-root module outputs no longer strip sensitivity marks from their
values, allowing dynamically sensitive values to propagate through the
configuration. We also remove the requirement for non-root module
outputs to be defined as sensitive if the value is marked as sensitive.

This avoids a static/dynamic clash when using shared modules that might
unknowingly receive sensitive values via input variables.

Co-authored-by: Martin Atkins <mart@degeneration.co.uk>
2021-04-21 14:27:03 -04:00
James Bardin 877348c031 wrong operation during destroy plan walk
The destroy plan walk was identifying itself as a normal plan, and
causing providers to be configured when they were not needed. Since the
provider configuration may not be complete during the minimal destroy
plan walk, validation or configuration may fail.
2021-04-19 12:35:10 -04:00
James Bardin d351d712c4 dynamic block MinItems MaxItems validation test 2021-04-15 17:34:33 -04:00
Alisdair McDiarmid 2390a11d60 core: Fix double-marked sensitive attributes
We need to unmark the decoded state and merge the marks with those from
the resource schema.

Co-authored-by: James Bardin <j.bardin@gmail.com>
2021-04-15 09:30:13 -04:00
Alisdair McDiarmid c1f7193454 lang/funcs: Make nonsensitive more permissive
Calling the nonsensitive function with values which are not sensitive
will result in an error. This restriction was added with the goal of
preventing confusingly redundant use of this function.

Unfortunately, this breaks when using nonsensitive to reveal the value of
sensitive resource attributes. This is because the validate walk does
not (and cannot) mark attributes as sensitive based on the schema,
because the resource value itself is unknown.

This commit therefore alters this restriction such that it permits
nonsensitive unknown values, and adds a test case to cover this specific
scenario.
2021-04-12 12:31:59 -04:00
James Bardin 4bfabbaee4 restore saved dependencies on delete error
Is a resource delete action fails and the provider returned a new state,
we need to ensure the stored dependencies are retained.
2021-04-08 09:57:14 -04:00
James Bardin 265b5106ca call the InConfigBody with addresses 2021-04-06 15:15:52 -04:00
James Bardin b6b7f78b49 ensure plans always have a stored state
When refresh was skipped for a destroy plan, there was no state stored
in the plan.
2021-04-01 16:44:32 -04:00
James Bardin 349e99bb0c don't force data reads from sibling module changes
Dependencies are tracked via configuration addresses, but when dealing
with depends_on references they can only apply to resources within the
same module instance. When determining if a data source can be read
during planning, verify that the dependency change is coming from the
same module instance.
2021-04-01 12:03:34 -04:00
James Bardin 8871eff495 remove debug Println 2021-04-01 12:03:34 -04:00
Alisdair McDiarmid c54c18680e core: Fix sensitive value/attribute conflict
When applying sensitivity marks to resources, we previously would first
mark any provider-denoted sensitive attributes, then apply the set of
planned-change sensitive value marks. This would cause a panic if a
provider marked an iterable value as sensitive, because it is invalid to
call `MarkWithPaths` against a marked iterable value.

Instead, we now merge the marks from the provider schema and the planned
change into a single set, and apply them with one call. The included
test panics without this change.
2021-03-30 15:51:09 -04:00
James Bardin 7964328f34 merge dependencies when refreshing
The resource configuration was always being used to determine
dependencies during refresh, because if there were no changes to a
resource, there was no chance to replace any incorrect stored
dependencies. Now that we are refreshing during plan, we can determine
that a resource has no changes and opt to store the new dependencies
immediately.

Here we clean up the writeResourceInstanceState calls to no longer
modify the resource instance state, removing the `dependencies`
argument. Callers are now expected to set the Dependencies field as
needed.
2021-03-29 14:34:01 -04:00
James Bardin 985124bfa8 failing test for removed cbd reference
A stored dependency is documented as being honored even after it is
removed from the configuration, until the referenced resource is
destroyed.
2021-03-25 17:39:53 -04:00
James Bardin 8cba2bfc39 check for unknowns when marking resource values
When we map schema sensitivity to resource values, there may be unknowns
when dealing with planned objects. Check for unknowns before iterating
over block values.
2021-03-23 17:06:18 -04:00
James Bardin 0ebc71383b
Merge pull request #28165 from hashicorp/jbardin/destroy-update-dep
Destroy then update dependency ordering
2021-03-23 11:04:55 -04:00
James Bardin 0bc64e3cc4 tests for destroy-then-update dependency ordering 2021-03-22 14:18:54 -04:00
Kristin Laemmert b9138f4465
terraform: validate providers' schemas during NewContext (#28124)
* checkpoint save: update InternalValidate tests to compare exact error

* configschema: extract and extend attribute validation

This commit adds an attribute-specific InternalValidate which was extracted directly from the block.InternalValidate logic and extended to verify any NestedTypes inside an Attribute. Only one error message changed, since it is now valid to have a cty.NilType for Attribute.Type as long as NestedType is set.

* terraform: validate provider schema's during NewContext

We haven't been able to guarantee that providers are validating their own schemas using (some version of) InternalValidate since providers were split out of the main codebase. This PR adds a call to InternalValidate when provider schemas are initially loaded by NewContext, which required a few other changes:

InternalValidate's handling of errors vs multierrors was a little weird - before this PR, it was occasionally returning a non-nil error which only stated "0 errors occurred" - so I addressed that in InternalValidate. I then tested this with a configuration that was using all of our most popular providers, and found that at least on provider had some invalid attribute names, so I commented that particular validation out. Adding that in would be a breaking change which we would have to coordinate with enablement and providers and (especially in this case) make sure it's well communicated to external provider developers.

I ran a few very unscientific tests comparing the timing with and without this validation, and it appeared to only cause a sub-second increase.

* refactor validate error message to closer match the sdk's message

* better error message

* tweak error message: move the instruction to run init to the end of the message, after the specific error.
2021-03-22 13:17:50 -04:00
James Bardin 8671f40768 connect destroyers to all stored create deps
We currently count on interconnecting destroy nodes to handle the
create->destroy dependency edge for replacement, but when the create
node is only an update we don't connect that edge directly.

Lookup all creators that are dependencies of the destory node and ensure
they are connected.
2021-03-21 12:14:47 -04:00
Pam Selle 34536daff9
Merge pull request #28036 from hashicorp/pselle/provider_sensitivity_non-experiment
Make provider sensitivity default behavior
2021-03-15 10:23:04 -04:00
James Bardin 1d4e1ed2b7 do not panic if there is no deposed state
NodeDestroyDeposedResourceInstanceObject should not panic if the deposed
state no longer exists.
2021-03-10 16:48:30 -05:00
Pam Selle 6ff1d2932e Conclude provider sensitivity experiment
Conclude the provider sensitivity experiment and make this
a default behavior.
2021-03-10 12:10:26 -05:00
James Bardin e6ab48addf test data source destroy with no provider 2021-03-08 21:43:47 -05:00
James Bardin 58b085f0dc prune unused providers from the graph, again
The provider transformers remove extra provider nodes when they are
initially setup, but it may turn out that they are not used later on.

The pruneUnusedNodesTransformer takes care of removing unused expansion
nodes, which originally required a provider, and hence may cause some
provider nodes to no longer be needed. We can also detect these and
remove them during the pruneUnusedNodesTransformer process.
2021-03-08 21:43:47 -05:00
James Bardin 7674e19d4e data source destroy nodes do not need a provider
Removing a data source is a state-only operation, and the node itself
does not require a provider.
2021-03-08 15:40:31 -05:00
James Bardin 3c6b2a8780 rename attachDataResourceDependsOnTransformer
Clarify the use of this transformer, interface and method which now does
not apply to anything but `depends_on` for data sources,
2021-03-08 15:39:09 -05:00
Kristin Laemmert ff05362d51
providers.Interface: rename ValidateDataSourceConfig to ValidateDataResourceConfig (#27874)
* providers.Interface: rename ValidateDataSourceConfig to
ValidateDataResourceConfig

This PR came about after renaming ValidateResourceTypeConfig to
ValidateResourceConfig: I now understand that we'd called it the former
instead of the latter to indicate that the function wasn't necessarily
operating on a resource that actually exists. A possibly-more-accurate
renaming of both functions might then be ValidateManagedResourceConfig
and ValidateDataResourceConfig.

The next commit will update the protocol (v6 only) as well; these are in
separate commits for reviewers and will get squashed together before
merging.

* extend renaming to protov6
2021-02-24 12:04:28 -05:00
James Bardin 160020a1e1
Merge pull request #27824 from hashicorp/jbardin/proxy-providers
Provider transformer cleanup
2021-02-23 10:54:41 -05:00
Pam Selle 8f7807684a Upgrade to quoted keywords to error
The warning about deprecation is upgraded to an error
2021-02-21 20:27:20 -05:00
James Bardin dd5227a3be provider transformer tests
remove some boilerplate when setting up tests
2021-02-19 10:56:55 -05:00
James Bardin 8c1703d8df simplify the use of configuration_aliases
Now that the possibility of extra provider nodes being added is gone, we
can skip the separate handling of configuration_aliases in the
ProviderConfigTransformer. Instead of adding concrete provider nodes for
configuration_aliases (which could be surprising later as the code
evolves), we implicitly add them based on the providers being passed in
by the parent module, using the same mechanism as non-aliased providers.

We can know that the `providers` map will be populated, because the
provider structures are validated while loading the configuration.
2021-02-19 10:56:55 -05:00
James Bardin b1d8d856ca remove ParentProviderTransformer
There is no longer any concept of a "parent provider". Inheritance of
default providers is discovered and connected in the ProviderTransformer
itself.
2021-02-19 10:56:55 -05:00