Commit Graph

288 Commits

Author SHA1 Message Date
James Bardin
583350a5c4 skip inter-provider cycle check in destroy plan
Just like in the destroy apply, we can skip the inter-provider cycle
check when creating the destroy plan, which can be expensive when there
are a lot of resource instances with dependencies from another provider.
2023-04-24 12:12:40 -04:00
Liam Cervante
aae6990d38
Add native plantimestamp function to Terraform (#32980)
* add plantimestamp function

* documentation

* add missing links

* fix typo
2023-04-21 09:47:28 +02:00
Liam Cervante
9c87006c34
checks: hide check diagnostics during plans that will not wait for approval (#32938)
* checks: filter out check diagnostics during certain plans

* wrap diagnostics produced by check blocks in a dedicated check block diagnostic

* address comments
2023-04-11 10:54:30 +02:00
James Bardin
c872cd6d96 the destroy plan should use correct type
When we plan to destroy an instance, the change recorded should use the
correct type for the resource rather than `DynamicPseudoType`. Most of
the time this is hidden when the change is encoded in the plan, because
any `null` is always encoded to the same value, and when decoded it will
be converted to the schema type. However when apply requires creating a
second plan for an instance's replacement that value is not going to be
encoded, and remains a dynamic value which is sent to the provider.

Most providers won't see that either, as the grpc request also encodes
and decodes the value to conform with the correct schema. The builtin
terraform provider does get the raw cty value though, and when that
dynamic value is returned validation fails when the type does not match.
2023-04-05 10:19:26 -04:00
Liam Cervante
84dc498b90
checks: always reference the nested data source from the check graph node (#32946)
* checks: always reference the nested data source from the check block graph node

* goimports
2023-04-05 08:48:42 +02:00
James Bardin
81b74cdb22 don't compare plan marks for missing values
If a resource has a change in marks from the prior state, we need to
notify the user that an update is going to be necessary to at least
store that new value in the state. If the provider however returns the
prior state value in lieu of a new config value, we need to be sure to
filter any new marks for comparison as well. The comparison of the prior
marks and new marks must take into account whether those new marks could
even be applied, because if the value is unchanged the new marks may be
completely irrelevant.
2023-03-28 15:55:15 -04:00
James Bardin
a4e92f3fca
Merge pull request #32876 from hashicorp/jbardin/state-serialize-plan-error
Remove planned data source objects from state on error
2023-03-28 15:50:59 -04:00
James Bardin
fdb00b9a46
Merge pull request #32900 from hashicorp/jbardin/target-drift-upgrade
External changes report can fail with schema migrations and `-target`
2023-03-28 15:50:38 -04:00
Liam Cervante
c06db2aadd
checks: don't iterate through all the nodes when there is nothing to search for (#32927) 2023-03-28 18:14:27 +02:00
Liam Cervante
5f97f88025
ensure checks are reported before executed (#32925) 2023-03-28 15:20:54 +02:00
Liam Cervante
978263efe9
Checks: Introduce check blocks into the terraform node and transform graph (#32735)
* Add support for scoped resources

* refactor existing checks addrs and add check block addr

* Add configuration for check blocks

* introduce check blocks into the terraform node and transform  graph

* address comments

* address comments

* don't execute checks during destroy operations

* don't even include check nodes for destroy operations
2023-03-23 16:07:31 +01:00
Liam Cervante
87c457781d
Checks: Refactor existing check addrs and add new check block addr (#32733)
* Add support for scoped resources

* refactor existing checks addrs and add check block addr

* address comments
2023-03-23 09:04:21 +01:00
James Bardin
240e345b45 test for untargeted schema mismatch 2023-03-21 12:55:26 -04:00
James Bardin
b10c4c54d9 prevent errors with -target and provider upgrades
In the case where a provider has been upgraded, and there are external
changes to resources outside of terraform, and -target is being used,
and resources which are not targeted require a schema migration; the
untargeted resources will not have been migrated and cannot be decoded for the
external changes report.

Since there is no way to decode the resources which have been excluded
via -target, we can only skip over them when inspecting
driftedResources. Return warnings for now to indicate that these
resources could not be decoded to help indicate that users will need to
eventually apply these changes.
2023-03-21 12:49:59 -04:00
James Bardin
defd7f0cde test that module outputs maintain sensitive marks 2023-03-20 14:22:08 -04:00
James Bardin
d33e627514 remove old comments 2023-03-20 14:22:08 -04:00
James Bardin
425c6bead2 store non-root sensitive outputs in state
Module outputs are evaluated from state, so in order to have detailed
information about sensitivity from non-root module outputs, we need to
store the value along with all sensitive marks. This aligns with the
usage of state being the in-memory store for other temporary values like
locals and variables.
2023-03-20 13:27:53 -04:00
James Bardin
1ca631bda0 remove planned objects from state on error
When planning encounters an error we were returning early without
cleaning out any planed data sources which cannot be serialized. Move
the cleanup to the common walkPlan method where the PriorState is
assigned so that it cannot be missed.
2023-03-17 08:45:42 -04:00
Martin Atkins
4e6e0bc47b core: Fix test flake in TestContext2Apply_stop
This test was previously not taking into account the fact that the
"Stopping" hook gets sent in the goroutine that calls ctx.Stop, whereas
all of the others get called from inside ctx.Apply, and so there are no
ordering guarantees for that event in relation to the others.

We now handle the stopping event as a special case that is allowed to
appear anywhere in the sequence as long as it appears. The other events
are still strongly ordered because their ordering is important for
correctness of Terraform Core's own behavior.

As some extra insurance we also now check whether the provider's
ApplyResourceChange and Stop functions both ran and reached a suitable
point of execution related to the stop request, which help to ensure not
only that something called Stop but that Terraform Core correctly
interacted with the provider to handle the stop.
2023-03-15 13:44:33 -07:00
Liam Cervante
af05cbb645
Add support for scoped resources (#32732) 2023-03-10 11:11:10 +01:00
Liam Cervante
32f151f20b
Update HCL to handle type mismatches when applying defaults (#32775)
* add test reproducing terraform crash

* pull latest hcl

* add missing go.sum file

* also fix tests broken by go-cty update
2023-03-09 14:29:58 +01:00
Alisdair McDiarmid
8df065a2fe initwd: Switch from earlyconfig to configs
This is a mostly mechanical refactor with a handful of changes which
are necessary due to the semantic difference between earlyconfig and
configs.

When parsing root and descendant modules in the module installer, we now
check the core version requirements inline. If the Terraform version is
incompatible, we drop any other module loader diagnostics. This ensures
that future language additions don't clutter the output and confuse the
user.

We also add two new checks during the module load process:

* Don't try to load a module with a `nil` source address. This is a
  necessary change due to the move away from earlyconfig.

* Don't try to load a module with a blank name (i.e. `module ""`).
  Because our module loading manifest uses the stringified module path
  as its map key, this causes a collision with the root module, and a
  later panic. This is the bug which triggered this refactor in the
  first place.
2023-03-06 09:14:28 -05:00
Martin Atkins
f0de9b60c1 backend/local: Periodically persist intermediate state snapshots
Terraform Core emits a hook event every time it writes a change into the
in-memory state. Previously the local backend would just copy that into
the transient storage of the state manager, but for most state storage
implementations that doesn't really do anything useful because it just
makes another copy of the state in memory.

We originally added this hook mechanism with the intent of making
Terraform _persist_ the state each time, but we backed that out after
finding that it was a bit too aggressive and was making the state snapshot
history much harder to use in storage systems that can preserve historical
snapshots.

However, sometimes Terraform gets killed mid-apply for whatever reason and
in our previous implementation that meant always losing that transient
state, forcing the user to edit the state manually (or use "import") to
recover a useful state.

In an attempt at finding a sweet spot between these extremes, here we
change the rule so that if an apply runs for longer than 20 seconds then
we'll try to persist the state to the backend in an update that arrives
at least 20 seconds after the first update, and then again for each
additional 20 second period as long as Terraform keeps announcing new
state snapshots.

This also introduces a special interruption mode where if the apply phase
gets interrupted by SIGINT (or equivalent) then the local backend will
try to persist the state immediately in anticipation of a
possibly-imminent SIGKILL, and will then immediately persist any
subsequent state update that arrives until the apply phase is complete.
After interruption Terraform will not start any new operations and will
instead just let any already-running operations run to completion, and so
this will persist the state once per resource instance that is able to
complete before being killed.

This does mean that now long-running applies will generate intermediate
state snapshots where they wouldn't before, but there should still be
considerably fewer snapshots than were created when we were persisting
for each individual state change. We can adjust the 20 second interval
in future commits if we find that this spot isn't as sweet as first
assumed.
2023-02-14 15:17:56 -08:00
Alisdair McDiarmid
b7042e818f
Merge pull request #32664 from hashicorp/alisdair/do-not-add-orphan-nodes-for-deposed-instances
Do not add orphan nodes for deposed instances
2023-02-13 09:50:48 -05:00
Alisdair McDiarmid
7ecb0b8ffb Do not add orphan nodes for deposed instances
Resource instances with no current object in state should not have
orphan nodes added to the graph, as deposed objects are handled
separately. This was previously handled correctly for the non-expanded
case, but expanded resources were missing the appropriate check for a
current object.

Also update the comment in the non-expanded case to hopefully clarify
that we're checking for the presence of a current object, not the
absence of any deposed objects. An instance may have both a current
object and zero or more deposed objects in some circumstances, and if
so, we still want an orphan node to be added if the instance is not in
configuration.
2023-02-10 16:25:11 -05:00
Alisdair McDiarmid
8997e5b8c6 Fix panic when planning orphaned deposed instances 2023-02-10 15:31:21 -05:00
Liam Cervante
24b88b7a72
Reverse the order of conversion/defaults, and update HCL with more flexible defaults package (#32454)
* Add failing test case for the given issue

* pause

* don't use local when sending PR for review

* go get github.com/hashicorp/hcl/v2@v2.16.0

* Update go.mod

---------

Co-authored-by: Alisdair McDiarmid <alisdair@users.noreply.github.com>
2023-01-31 06:37:24 -05:00
James Bardin
47fed6d31e save null module outputs in state
Although they are not serialized to the final stored state, all module
outputs must be saved in the state for evaluation. There is no defined
schema which is used to identify the overall type of module outputs, so
all outputs must exist in the state to build the correct type for proper
evaluation.
2023-01-26 11:03:23 -05:00
James Bardin
45cb0489d0 test references only from output preconditions
These references were getting dropped, which could cause the referenced
nodes to be pruned from the graph.
2023-01-05 10:01:25 -05:00
James Bardin
1790f844b3 output refs missing error_message
Output references must also include the error_message expression.
Fix the early return in referencesForOutput, which could skip
preconditions. The small slice allocation optimization is not really
needed here, since this is not a hot path at all.
2023-01-05 09:59:52 -05:00
James Bardin
721df0e68d
Merge pull request #32395 from hashicorp/jbardin/plan-output-on-error
Always show and store planned actions and checks even when planning fails
2023-01-04 12:44:52 -05:00
James Bardin
d493e998e1 add resource address to log message 2022-12-21 10:53:11 -05:00
James Bardin
0c1aaba635 fix invalid null blocks during refresh
Legacy providers may return null values for nested blocks during
refresh. Because the ReadResource call needs to accept any value to
allow the provider to report external changes, we allowed all changes to
the value as long as the underlying cty.Type was correct, allowing
null block values to be inserted into the state.

While technically invalid, we needed to accept these null values for
compatibility, and they were mostly seen as a nuisance, causing noise in
external changes and plan output. These null block values however can be
inserted into the effective configuration with the use of
`ignore_changes`, which can cause problems where the configuration is
assumed to be completely valid.

Rather than accept the null values, we can insert empty container values
for these blocks when refreshing the instance, which will prevent any
invalid values from entering state at all. Because these must still be
accepted for compatibility, we can only log the difference as a warning.
Currently the NormalizeObjectFromLegacySDK does not report which
specific blocks it fixed, so we just log a generic message.
2022-12-21 10:18:26 -05:00
James Bardin
bb5f360747 always report condition errors
The status in the face of errors didn't matter before, because we never
wrote out a plan with errors.
2022-12-14 14:45:04 -05:00
Martin Atkins
6d9ddbacec core: Mark errored plans as errored
In any situation where we return a plan object along with some errors
we'll also explicitly annotate the plan object as being errored so that
we can catch if someone accidentally tries to apply that incomplete plan.

At the moment this situation is impossible to reach but in a later commit
we'll make it possible to save errored plans to disk for further
inspection, at which point it'll become important to not allow applying
them.
2022-12-12 17:17:42 -05:00
Martin Atkins
6611e3a9cd core: Possibly return a partial plan alongside errors
For some kinds of plan failure we will already have successfully completed
planning for at least one upstream object before encountering a downstream
error.

Since a downstream failure can be caused by an already-recorded action
from upstream, it might be helpful to inspect the actions planned so far
in order to understand better why the error occurred.

This doesn't yet make this result visible anywhere, and is backward
compatible with existing callers because they currently entirely ignore
the returned plan pointer if the diagnostics contains at least one error.
2022-12-12 17:17:42 -05:00
Bryan Stenson
b2f6813341
typo (#32327) 2022-12-09 16:14:01 +00:00
James Bardin
cbcae8478f
Merge pull request #32209 from hashicorp/jbardin/data-source-destroy-edges
ensure destroy edges from data sources
2022-12-01 10:25:42 -05:00
James Bardin
dcd762e81d evaluate outputs from state
Outputs were being evaluated from changes, even during apply. Make sure
we update the state correctly, and remove the existing change. This
requires adding more Planning fields to the output nodes to
differentiate whether the output is being planned or applied because the
same type handles both cases. We can evaluate separately whether new
types should be introduced to deal with both cases.

The module node cleanup was also prematurely removing module outputs
from the state before evaluation. This was not noticed before because
the evaluation was always falling back to changes. Have the root module
node do the final cleanup for all its children.

It turns out sensitive was also being handled incorrectly, and only
sensitive from configuration was being considered. Make sure to mark the
output as sensitive when storing sensitive values into state, and OR
sensitive marks with the state config when evaluating the output values.
2022-11-28 16:39:55 -05:00
James Bardin
c9d6f82ac5 don't re-set changes for refreshed outputs
When output values are updated in the refreshed state, we don't need to
re-set the changes which were already set in conjunction with the
current state.
2022-11-28 16:37:23 -05:00
James Bardin
2b14670dfd
Merge pull request #32260 from hashicorp/jbardin/resolved-provided-by
ProvidedBy should return the resolved provider
2022-11-22 09:53:41 -05:00
James Bardin
60f82eea40
Merge pull request #32236 from hashicorp/jbardin/1.3-destroy-perf
check walkDestroy to help DestroyEdgeTransformer
2022-11-22 09:45:32 -05:00
James Bardin
8e18922170 ProvidedBy should return the resolved provider
Once the ProviderTransformer has resolved and set the exact provider,
the ProvidedBy method should return that exact provider again.

We can hoist the stored provider addr into the AbstractInstance and
avoid the method duplication and slight differences between the
implementations.
2022-11-22 09:41:53 -05:00
James Bardin
7946e4a88a a deleted orphan should have no plan
If when refreshing an orphaned instance the provider indicates it has
already been deleted, there is no reason to create a change for that
instance. A NoOp change should only represent an object that exists and
is not changing.

This was likely left in before in order to try and provide a record of
the change for external consumers of the plan, but newer plans also
contain all changes made outside of Terraform which better accounts for
the difference. The NoOp change now can cause problems, because it may
represent an instance with conditions to check even though that instance
does not exist.
2022-11-18 08:48:15 -05:00
James Bardin
b6a67f622f check walkDestroy to help DestroyEdgeTransformer
In a heavily-connected graph with lots of inter-dependent providers, the
cycle checks for destroy edges across providers can seriously impact
performance. Since the specific cases we need to avoid will involve
create/update nodes, skip the extra checks during a full destroy
operation. Once we find a way to better track these dependencies, the
transformer will not need to do the cycle checks in the first place.
2022-11-17 13:29:09 -05:00
James Bardin
ebd5a17b17 ensure destroy edges from data sources
Data resource dependencies are not stored in the state, so we need to
take the latest dependency set to use for any direct connections to
destroy nodes.
2022-11-11 14:56:09 -05:00
James Bardin
3db3ed03fb ensure destroy plan contains valid state values
Some prior refactors left the detroyPlan method a bit confusing, and ran
into a case where the previous run state could be returned as nil.

Get rid of the no longer used pendingPlan value, and track the prior and
prev states directly, making sure we always have a value for both.
2022-11-11 14:34:21 -05:00
James Bardin
3ea704ef81 Make the pre-destroy refresh a full plan
In order to complete the terraform destroy command, a refresh must first
be done to update state and remove any instances which have already been
deleted externally. This was being done with a refresh plan, which will
avoid any condition evaluations and avoid planning new instances. That
however can fail due to invalid references from resources that are
already missing from the state.

A new plan type to handle the concept of the pre-destroy-refresh is
needed here, which should probably be incorporated directly into the
destroy plan, just like the original refresh walk was incorporated into
the normal planning process. That however is major refactoring that is
not appropriate for a patch release.

Instead we make two discrete changes here to prevent blocking a destroy
plan. The first is to use a normal plan to refresh, which will enable
evaluation because missing and inconsistent instances will be planned
for creation and updates, allowing them to be evaluated. That is not
optimal of course, but does revert to the method used by previous
Terraform releases until a better method can be implemented.

The second change is adding a preDestroyRefresh flag to the planning
process. This is checked in any location which evalCheckRules is called,
and lets us change the diagnosticSeverity of the output to only be
warnings, matching the behavior of a normal refresh plan.
2022-11-11 14:33:50 -05:00
Liam Cervante
0c7fda1906
Update HCL and go-cty to fix optional and default attributes (#32178)
* Add test cases to verify all the default and optional issues are fixed

* actually commit all the tests

* update go-cty

* Update hcl
2022-11-10 14:00:16 +00:00
James Bardin
1100eae89f use UIMode instead of 0 changes to detect refresh 2022-11-02 10:56:08 -04:00