Commit Graph

54 Commits

Author SHA1 Message Date
James Bardin
ddb2bbf4e9 Read orphaned resources during plan
This forces orphaned resources to be re-read during planning, removing
them from the state if they no longer exist.

This needs to be done for a bare `refresh` execution, since Terraform
should remove instances that don't exist and are not in the
configuration from the state. They should also be removed from state so
there is no Delete change planned, as not all providers will gracefully
handle a delete operation on a resource that does not exist.
2020-10-22 09:46:42 -04:00
Pam Selle
02c48f8071 Comment fixing 2020-10-18 13:00:09 -04:00
James Bardin
35714e61e6 audit graph builder to make them more similar
Auditing the graph builder to remove unused transformers (planning does
not need to close provisioners for example), and re-order them. While
many of the transformations are commutative, using the same order
ensures the same behavior between operations when the commutative
property is lost or changed.
2020-10-06 17:39:53 -04:00
James Bardin
84f7116ac8 thread skipContext through to the instance node 2020-09-24 09:34:49 -04:00
James Bardin
8105096ec8 attach dependencies during plan
This was previously done during refresh alone, now we need to insert
these during the refresh portion of plan.
2020-09-21 16:17:45 -04:00
Kristin Laemmert
c9f710ac29
terraform: remove DisableReduce from refresh, plan and apply graphs (#25824) 2020-08-14 14:13:33 -04:00
James Bardin
0df5a7e6cf Generalize target addresses before expansion
Before expansion happens, we only have expansion resource nodes that
know their ConfigResource address. In order to properly compare these to
targets within a module instance, we need to generalize the target to
also be a ConfigResource.

We can also remove the IgnoreIndices field from the transformer, since
we have addresses that are properly scoped and can compare them in the
correct context.
2020-08-12 10:12:43 -04:00
James Bardin
308eb5f47f add CountBoundaryTransformer after targeting
no need to have the extra nodes and edges in the graph when we're
traversing everything for targeting
2020-06-23 17:22:44 -04:00
James Bardin
a8e0914d7f attach dependency type name changes 2020-05-18 21:35:37 -04:00
James Bardin
23e259a68c add AttachDependsOnTransformer to plan
This transformer is what will provider the data sources with the
transitive dependencies needed to determine if they can read during plan
or must be deferred.
2020-05-13 13:58:11 -04:00
James Bardin
73492fd2d5 add module expansion to validation
We cannot evaluate expansion during validation, since the values may not
be known at that time.

Inject a nodeValidateModule, using the "Concrete" pattern used for other
node types during graph building. This node will always evaluate to a
single module instance, so that we have a valid context within which to
evaluate all sub resources.
2020-04-05 12:13:48 -04:00
James Bardin
0dcca1bc37 make the root node a nodeCloseModule for root
Replace the graphNodeRoot for the main graph with a nodeCloseModule for
the root module. USe a new transformer as well, so as to not change any
behavior of DynamicExpand graphs.

Closing out the root module like we do with sub modules means we no
longer need the OrphanResourceTransformer, or the NodeDestroyResource.
The old resource destroy logic has mostly moved into the instance nodes,
and the remaining resource node was just for cleanup, which need to be
done again by the module since there isn't always a NodeDestroyResource
to be evaluated.

The more-correct state caused a few tests to fail, which need to be
cleaned up to match the state without empty resource husks.
2020-04-02 16:00:36 -04:00
James Bardin
40f09027f0 expand planned resources
While the Expander itself now handles the recursive expansion of
modules, Resources themselves still need to be expanded twice, because
the evaluation of the Resource, which entails evaluating the for_each or
count expressions, is separate from the ResourceInstance expansion.

Add a nodeExpandPlannableResource to do handle this expansion to allow
all NodePlannableResources to call EvalWriteResourceState with an
absolute address.
2020-03-25 17:03:06 -04:00
Kristin Laemmert
c7cc0afb80
Mildwonkey/ps schema (#24312)
* add Config to AttachSchemaTransformer for providerFqn lookup
* terraform: refactor ProvidedBy() to return nil when provider is not set
in config or state
2020-03-10 14:43:57 -04:00
Martin Atkins
68b900928d core: Use instances.Expander to handle resource count and for_each
This is a minimal integration of instances.Expander used just for resource
count and for_each, for now just forcing modules to always be singletons
because the rest of Terraform Core isn't ready to deal with expanding
module calls yet.

This doesn't integrate super cleanly yet because we still have some
cleanup work to do in the design of the plan walk, to make it explicit
that the nodes in the plan graph represent static configuration objects
rather than expanded instances, including for modules. To make this work
in the meantime, there is some shimming between addrs.Module and
addrs.ModuleInstance to correct for the discontinuities that result from
the fact that Terraform currently assumes that modules are always
singletons.
2020-02-14 15:20:07 -08:00
Martin Atkins
b229264bd6 core: A "go fmt" catchup
Since we started using experimental Go Modules our editor tooling hasn't
been fully functional, apparently including format-on-save support. This
is a catchup to get everything back straight again.
2018-10-16 19:14:11 -07:00
Martin Atkins
a806bb7d8c core: OrphanResourceTransformer -> OrphanResourceInstanceTransformer
This transformer creates resource _instance_ nodes rather than resource
nodes, so this name is a clearer descriptor for what it does.
2018-10-16 19:14:11 -07:00
Martin Atkins
a43b7df282 core: Handle forced-create_before_destroy during the plan walk
Previously we used a single plan action "Replace" to represent both the
destroy-before-create and the create-before-destroy variants of replacing.
However, this forces the apply graph builder to jump through a lot of
hoops to figure out which nodes need it forced on and rebuild parts of
the graph to represent that.

If we instead decide between these two cases at plan time, the actual
determination of it is more straightforward because each resource is
represented by only one node in the plan graph, and then we can ensure
we put the right nodes in the graph during DiffTransformer and thus avoid
the logic for dealing with deposed instances being spread across various
different transformers and node types.

As a nice side-effect, this also allows us to show the difference between
destroy-then-create and create-then-destroy in the rendered diff in the
CLI, although this change doesn't fully implement that yet.
2018-10-16 19:14:11 -07:00
Martin Atkins
334c6f1c2c core: Be more explicit in how we handle create_before_destroy
Previously our handling of create_before_destroy -- and of deposed objects
in particular -- was rather "implicit" and spread over various different
subsystems. We'd quietly just destroy every deposed object during a
destroy operation, without any user-visible plan to do so.

Here we make things more explicit by tracking each deposed object
individually by its pseudorandomly-allocated key. There are two different
mechanisms at play here, building on the same concepts:

- During a replace operation with create_before_destroy, we *pre-allocate*
  a DeposedKey to use for the prior object in the "apply" node and then
  pass that exact id to the destroy node, ensuring that we only destroy
  the single object we planned to destroy. In the happy path here the
  user never actually sees the allocated deposed key because we use it and
  then immediately destroy it within the same operation. However, that
  destroy may fail, which brings us to the second mechanism:

- If any deposed objects are already present in state during _plan_, we
  insert a destroy change for them into the plan so that it's explicit to
  the user that we are going to destroy these additional objects, and then
  create an individual graph node for each one in DiffTransformer.

The main motivation here is to be more careful in how we handle these
destroys so that from a user's standpoint we never destroy something
without the user knowing about it ahead of time.

However, this new organization also hopefully makes the code itself a
little easier to follow because the connection between the create and
destroy steps of a Replace is reprseented in a single place (in
DiffTransformer) and deposed instances each have their own explicit graph
node rather than being secretly handled as part of the main instance-level
graph node.
2018-10-16 19:14:11 -07:00
Martin Atkins
7d760c09fb core: Update EvalCountFixZeroOneBoundaryGlobal for new state types 2018-10-16 19:14:11 -07:00
Martin Atkins
a3403f2766 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-10-16 19:11:09 -07:00
James Bardin
a2c76a28f5 core: run ProvisionerTransformer during plan
This makes sure the graph is complete for validation
2018-10-16 18:49:20 -07:00
Martin Atkins
71cedf19a4 core: Don't create indirect provider dependencies for references
The prior commit changed the schema-access model so that all schemas are
fetched up front during context creation and are then readily available
for use throughout graph building and evaluation.

As a result, we no longer need to create dependency edges to a provider
when one of its resources is referenced by another node, and so the
ProviderTransformer needs only to worry about direct ownership
dependencies.

This also avoids the need for us to run AttachSchemaTransformer twice,
since ProviderTransformer no longer needs schema and we can therefore
defer attaching until just before ReferenceTransformer, when all of the
referencable and referencing nodes are already present in the graph.
2018-10-16 18:49:20 -07:00
Martin Atkins
f7aa06726a core: Run AttachSchemaTransformer twice to catch provider nodes too
Both ProviderTransformer and ReferenceTransformer need schema information,
and so there's a chicken-and-egg problem here where previously the schemas
were not getting attached to provider nodes created during
ProviderTransformer.

As a stop-gap measure for now we'll just run AttachSchemaTransformer
twice, so we can catch any new nodes created during the provider
transforms.
2018-10-16 18:49:20 -07:00
Martin Atkins
88b5607a7a core: Fetch schemas during context construction
Previously we fetched schemas during the AttachSchemaTransformer,
potentially multiple times as that was re-run for each graph built. Now
we fetch the schemas just once during context construction, passing that
result into each of the graph builders.

This only addresses the schema accesses during graph construction. We're
still separately loading schemas during the main walk for evaluation
purposes. This will be addressed in a later commit.
2018-10-16 18:49:20 -07:00
James Bardin
4d2da4d733 connect non-resources to providers they reference
Any non-resource (outputs, variables, locals) that references a resource
type must also be connected to that resources provider. This is required
during apply, because the graph built from the diff may not include the
referenced resources because they are being evaluated from the state.

If the provider isn't present already, add a NodeEvalableProvider to
fetch the provider schema.

The provider transformers now need to happen after the outputs, locals,
and variables are transformed.
2018-10-16 18:49:20 -07:00
Martin Atkins
dd6b171f62 core: Make provisioner schemas available to plan resource instance nodes
This requires making the "components" object available to the resource
node so it can be used during DynamicExpand. It also involved splitting
the provisioner schema attachment into a separate interface from
GraphNodeProvisionerConsumer so that it can now be handled within
AttachSchemaTransformer, along with all of the other schema attachment
steps.
2018-10-16 18:49:20 -07:00
Martin Atkins
d4285dd27f core: Attach resource and provider config schemas during graph build
This is a little awkward since we need to instantiate the providers much
earlier than before. To avoid a lot of reshuffling here we just spin each
one up and then immediately shut it down again, letting our existing init
functionality during the graph walk still do the main initialization.
2018-10-16 18:46:46 -07:00
Martin Atkins
c937c06a03 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-10-16 18:46:46 -07:00
James Bardin
7e4dcdb9f0 run RemovedModuleTransformer before References
Also add RemovedModuleTransformer to the plan graph for parity.
2017-11-09 10:34:56 -05:00
James Bardin
9283568dca add OrphanOutputTransformer to the plan graph
make sure orphaned outputs appear in the plan as well
2017-11-08 14:28:02 -05:00
James Bardin
2f91007999 group the provider transformations
The series of provider transformations is important, and often repeated.
Group these together in a single transform function.
2017-11-02 15:00:06 -04:00
James Bardin
0986d01223 add providers directly from the configuration
The first step in only using the required provider nodes in a graph is
to be able to specifically add them from the configuration.

The MissingProviderTransformer was previously responsible for adding
all providers. Now it is really just adding any that are missing from
the config.
2017-11-02 15:00:06 -04:00
James Bardin
1ad97f6be8 use an EvalOpFilter for module variables
Remove the Input flag threaded through the input graph creation process
to prevent interpolation failures on module variables.
Use an EvalOpFilter instead to inset the correct EvalNode during
walkInput. Remove the EvalTryInterpolate type, and use the same
ContinueOnErr flag as the output node for consistency and to try and
keep the number possible eval node types down.
2017-10-02 16:20:29 -04:00
Martin Atkins
5b66953d1d core: graph nodes and edges for local values
A local value is similar to an output in that it exists only within state
and just always evaluates its value as best it can with the current state.
Therefore it has a single graph node type for all walks, which will
deal with that evaluation operation.
2017-08-21 15:15:25 -07:00
James Bardin
97bb7cb65c Don't allow interpolation failure to stop Input
Allow module variables to fail interpolation during input. This is OK
since they will be verified again during Plan.  Because Input happens
before Refresh, module variable interpolation can fail when referencing
values that aren't yet in the state, but are expected after Refresh.
2017-08-10 14:14:29 -04:00
Martin Atkins
a8c58b081c core: -target option to also select resources in descendant modules
Previously the behavior for -target when given a module address was to
target only resources directly within that module, ignoring any resources
defined in child modules.

This behavior turned out to be counter-intuitive, since users expected
the -target address to be interpreted hierarchically.

We'll now use the new "Contains" function for addresses, which provides
a hierarchical "containment" concept that is more consistent with user
expectations. In particular, it allows module.foo to match
module.foo.module.bar.aws_instance.baz, where before that would not have
been true.

Since Contains isn't commutative (unlike Equals) this requires some
special handling for targeting specific indices. When given an argument
like -target=aws_instance.foo[0], the initial graph construction (for
both plan and refresh) is for the resource nodes from configuration, which
have not yet been expanded to separate indexed instances. Thus we need
to do the first pass of TargetsTransformer in mode where indices are
ignored, with the work then completed by the DynamicExpand method which
re-applies the TargetsTransformer in index-sensitive mode.

This is a breaking change for anyone depending on the previous behavior
of -target, since it will now select more resources than before. There is
no way provided to obtain the previous behavior. Eventually we may support
negative targeting, which could then combine with positive targets to
regain the previous behavior as an explicit choice.
2017-06-16 16:36:08 -07:00
Chris Marchesi
d41b806789 core: Restore CountBoundaryTransformer to apply, add/adjust tests
Moving the transformer wholesale looks like it broke some tests, with
some actually doing legit work in normalizing singular resources from a
foo.0 notation to just foo.

Adjusted the TestPlanGraphBuilder to account for the extra
meta.count-boundary nodes in the graph output now, as well as added
another context test that tests this case. It appears the issue happens
during validate, as this is where the state can be altered to a broken
state if things are not properly transformed in the plan graph.
2017-04-19 22:23:52 -07:00
Chris Marchesi
2802d319d2 core: Move CountBoundaryTransformer to the plan graph builder
This fixes interpolation issues on grandchild data sources that have
multiple instances (ie: counts). For example, baz depends on bar, which
depends on foo.

In this instance, after an initial TF run is done and state is saved,
the next refresh/plan is not properly transformed, and instead of the
graph/state coming through as data.x.bar.0, it comes through as
data.x.bar.  This breaks interpolations that rely on splat operators -
ie: data.x.bar.*.out.
2017-04-19 16:56:54 -07:00
Sander van Harmelen
051582d32a Add the close provider and provisioner transformers (#13102) 2017-04-12 23:25:15 +02:00
Mitchell Hashimoto
86cbcff962
terraform: fixup a merge issue
We forgot to wrap some changes from the old branch into the new style
2017-01-25 12:32:09 -08:00
Mitchell Hashimoto
1427075005
terraform: wip moving validation to new graph 2017-01-25 12:28:07 -08:00
Mitchell Hashimoto
66f6f70cdb
terraform: input graph 2017-01-25 12:28:07 -08:00
Mitchell Hashimoto
7c014b84b6
terraform: handle count fields for data sources 2017-01-22 16:05:10 -08:00
Mitchell Hashimoto
89f7e3b79f
terraform: add module vars after providers to see references
Fixes #10711

The `ModuleVariablesTransformer` only adds module variables in use. This
was missing module variables used by providers since we ran the provider
too late. This moves the transformer and adds a test for this.
2016-12-13 21:22:21 -08:00
Mitchell Hashimoto
5f1e6ad020
terraform: TargetsTransformer should preserve module variables
Fixes #10680

This moves TargetsTransformer to run after the transforms that add
module variables is run. This makes targeting work across modules (test
added).

This is a bug that only exists in the new graph, but was caught by a
shadow error in #10680. Tests were added to protect against regressions.
2016-12-12 20:59:14 -08:00
Mitchell Hashimoto
26ac58bc97
terraform: refactor NodeApplyableProvider to use NodeAbstractProvider
This is important so that the graph looks correct.
2016-12-03 15:27:38 -08:00
Mitchell Hashimoto
fb8f2e2753
terraform: new Graph API that can return the graph for each op 2016-12-02 22:56:22 -05:00
James Bardin
3df3b99276 Make sure each GraphBuilder has a Name
Ensure that each instance of BasucGraphBuilder gets a name corresponding
to the Builder which created it. This allows us to differentiate the
graphs in the logs.
2016-11-15 16:40:10 -05:00
Mitchell Hashimoto
1efdba9b30
terraform: target at the right moment to get the right values 2016-11-08 13:59:30 -08:00