Commit Graph

2279 Commits

Author SHA1 Message Date
Martin Atkins
9af67806fc core: Prune placeholder objects from state after refresh
Prior to our refactoring here, we were relying on a lucky coincidence for
correct behavior of the plan walk following a refresh in the same run:

- The refresh phase created placeholder objects in the state to represent
  any resource instance pending creation, to allow the interpolator to
  read attributes from them when evaluating "provider" and "data" blocks.
  In effect, the refresh walk is creating a partial plan that only covers
  creation actions, but was immediately discarding the actual diff entries
  and storing only the planned new state.

- It happened that objects pending creation showed up in state with an
  empty ID value, since that only gets assigned by the provider during
  apply.

- The Refresh function concluded by calling terraform.State.Prune, which
  deletes from the state any objects that have an empty ID value, which
  therefore prevented these temporary objects from surviving into the
  plan phase.

After refactoring, we no longer have this special ID field on instance
object state, and we instead rely on the Status field for tracking such
things. We also no longer have an explicit "prune" step on state, since
the state mutation methods themselves keep the structure pruned.

To address this, here we introduce a new instance object status "planned",
which is equivalent to having an empty ID value in the old world. We also
introduce a new method on states.SyncState that deletes from the state
any planned objects, which therefore replaces that portion of the old
State.prune operation just for this refresh use-case.

Finally, we are now expecting the expression evaluator to pull pending
objects from the planned changeset rather than from the state directly,
and so for correct results these placeholder resource creation changes
must also be reported in a throwaway changeset during the refresh walk.

The addition of states.ObjectPlanned also permits a previously-missing
safety check in the expression evaluator to prevent us from relying on the
incomplete value stored in state for a pending object, in the event that
some bug prevents the real pending object from being written into the
planned changeset.
2018-10-16 19:14:11 -07:00
Martin Atkins
40f00d8db5 core: StateReferences method should return []addrs.Referenceable
We no longer use strings to represent addresses, so this method was a
leftover outlier from previous refactoring efforts.

At this time the result is not actually being used due to the state type
refactoring, which is a bug we'll address in a subsequent commit.
2018-10-16 19:14:11 -07:00
Martin Atkins
59175e466e core: Extra TRACE logging in the eval_state.go eval nodes.
Tracking when each instance's state is read, written, or removed is often
very useful in debugging strange interactions.
2018-10-16 19:14:11 -07:00
Martin Atkins
239a54ad6f command: initial structural diff rendering
This is a light adaptation of our earlier prototype of structural diff
rendering, as a starting point for what we'll actually ship. This is not
consistent with the latest mocks, so will need some additional work before
it is ready, but integrating this allows us to at least see the plan
contents while fixing up remaining issues elsewhere.
2018-10-16 19:14:11 -07:00
Martin Atkins
1ced176fc6 plans: Track RequiredReplace as a cty.PathSet
We were previously tracking this as a []cty.Path, but having it turned
into a pathset on creation makes downstream use of it more convenient and
ensures that it'll obey expected invariants like not containing the same
path twice.
2018-10-16 19:14:11 -07:00
Martin Atkins
d54b52fa01 core: Fix error reporting for malformed provider response values 2018-10-16 19:14:11 -07:00
Martin Atkins
235f582ae5 core: Re-implement EvalReadDataApply against new provider interface 2018-10-16 19:14:11 -07:00
Martin Atkins
182e783885 core: EvalReadDataDiff to output direct config value alongside planned
We're now writing the "planned new value" to OutputValue, but the data
resource nodes during refresh need to see the verbatim config value in
order to decide whether read must be deferred to the apply phase, so we'll
optionally export that here too.
2018-10-16 19:14:11 -07:00
Martin Atkins
20adb9d9b7 core: Evaluate resource references from plan where possible
Our state representation is not able to preserve unknown values, so it's
not suitable for retaining the transient incomplete values we produce
during planning.

Instead, we'll discard the unknown values when writing to state and have
the expression evaluator prefer an object from the plan where possible.
We still use the shape of the transient state to inform things like the
resource's "each mode", so the plan only masks the object values
themselves.
2018-10-16 19:14:11 -07:00
Martin Atkins
1afdb055ca core: Re-implement ReadDataDiff around our new approach
This is no longer a call into the provider, since all of the data diff
logic is standard for all data sources anyway. Instead, we just compute
the planned new value and construct a planned change from that as-is.

Previously the provider could, in principle, customize the read diff. In
practice there is no real reason to do that and the existing SDK didn't
pass that possibility through to provider code, so we can safely change
this without impacting provider compatibility.
2018-10-16 19:14:11 -07:00
Martin Atkins
7249a73f79 core: Don't panic if "required replace" path doesn't resolve to a value 2018-10-16 19:14:11 -07:00
Martin Atkins
6acf335e60 core: Fix evaluation of collections of resource instances 2018-10-16 19:14:11 -07:00
Martin Atkins
1d672623eb core: Remove changes from the plan after they are applied 2018-10-16 19:14:11 -07:00
Martin Atkins
a7342de274 core: Properly handle no-op changes in plan
Previously we just left these out of the plan altogether, but in the new
plan types we intentionally include change information for every resource
instance, even if no changes are actually planned, to allow alternative
plan file viewers to show what isn't changing as well as what is.
2018-10-16 19:14:11 -07:00
Martin Atkins
3d86dc51e0 core: Re-implement EvalReadDiff for the new plan types
This also includes passing in the provider schema to a few more EvalNodes
that were expecting it but not getting it, in order to be able to
successfully test the implementation of EvalReadDiff here.
2018-10-16 19:14:11 -07:00
Martin Atkins
bd299b9a22 core: Re-implement EvalWriteDiff to work with new plan types 2018-10-16 19:14:11 -07:00
Martin Atkins
ec11efc50a core: Tolerate the prior state being nil in EvalDiff
This happens legitimately in situations where we'll be creating an object
for this resource instance for the first time.
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
ed7e331041 terraform: Return validation diagnostics with source info where possible 2018-10-16 19:14:11 -07:00
Martin Atkins
44bc7519a6 terraform: More wiring in of new provider types
This doesn't actually work yet, but it builds and then panics in a pretty
satisfying way.
2018-10-16 19:12:54 -07:00
James Bardin
0b76c42ad2 replace provider and provisioner types in tests
The field assignments and methods are incorrect still, but the type
definitions and returns are now updated.
2018-10-16 19:11:09 -07:00
James Bardin
08a8834882 ResourceProvisioner to provisioners.Interface
Replacing the core types, without touching tests yet.
2018-10-16 19:11:09 -07:00
James Bardin
ad7eee7ba4 update Refresh
Use the new ReadResource provider method
2018-10-16 19:11:09 -07:00
James Bardin
16df9c37cf first step in core provider type replacement
Chaange ResourceProvider to providers.Interface starting from the
context, and fix all type errors.

This only replaced some of method calls directly applicable to the
providers themselves. The resource methods will follow.
2018-10-16 19:11:09 -07:00
James Bardin
bddfd0412c add new provider and provisioner mocks
MockProvider and MockProvisioner implement the new plugin interfaces,
and are built following the patterns used by the legacy
MockResourceProvider and MockResourceProvisioner
2018-10-16 19:11:09 -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
Martin Atkins
479c6b2466 move "configschema" from "config" to "configs"
The "config" package is no longer used and will be removed as part
of the 0.12 release cleanup. Since configschema is part of the
"new world" of configuration modelling, it makes more sense for
it to live as a subdirectory of the newer "configs" package.
2018-10-16 18:50:29 -07:00
Martin Atkins
e4efe92e83 core: validate that depends_on addresses are for objects
Since the "References" function on graph nodes can't return errors, we
need to catch invalid depends_on references during the validation pass.

In this case, we're checking that the address is exact, rather than being
part of a traversal into an attribute of the object. In other words,
aws_instance.example is valid but aws_instance.example.id is not.
2018-10-16 18:50:29 -07:00
Martin Atkins
2d9c779784 core: Assorted small test fixes
Rebasing the v0.12 dev branch to master caught a few changes that didn't
pass tests afterwards, so this is a catchup commit to fix those.
2018-10-16 18:50:29 -07:00
Martin Atkins
cf4a5e6336 core: Don't DynamicExpand during validate
Previously we would attempt to DynamicExpand during the validate walk and
then validate each expanded instance separately. However, this meant that
we would not be able to validate the contents of a block where count = 0
or if count is not yet known.

Here we instead do a more static validation pass against the resource
configuration itself, setting count.index to cty.UnknownVal(cty.Number) so
we can type-check everything inside the block as being correct regardless
of the final count.

This is another step towards repairing the "validate" command for our
changed assumptions in a world where we have a more sophisticated type
checker.

This doesn't yet address the remaining problem that the expression
evaluator can't, with the current state structures, distinguish between
a completed resource with count = 0 and a resource that doesn't exist
at all (during validate), and so we'll still get errors if an expression
elsewhere in configuration refers to a dynamic index of a resource with
"count" set. That's a pre-existing condition that's no longer being masked
by _this_ problem, but can't be addressed until we've introduced the new
state types (states.State, etc) and thus we _can_ distinguish these two
situations. That will therefore be addressed in a later commit.
2018-10-16 18:50:29 -07:00
Martin Atkins
fd371d838d core: Handle count.index evaluation more explicitly
Previously we had the evaluate methods accept directly an
addrs.InstanceKey and had our evaluator infer a suitable value for
count.index for it, but that prevents us from setting the index to be
unknown in the validation scenario where we may not be able to predict
the number of instances yet but we still want to be able to check that
the configuration block is type-safe for all possible count values.

To achieve this, we separate the concern of deciding on a value for
count.index from the concern of evaluating it, which then allows for
other implementations of this in future. For the purpose of this commit
there is no change in behavior, with the count.index value being populated
whenever the instance key is a number.

This commit does a little more groundwork for the future implementation
of the for_each feature (which'll support each.key and each.value) but
still doesn't yet implement it, leaving it just stubbed out for the
moment.
2018-10-16 18:50:29 -07:00
Martin Atkins
f77e7a61b0 various: helpers for collecting necessary provider types
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.

Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.

State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.

Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.

A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
2018-10-16 18:50:29 -07:00
Martin Atkins
2ef56b3e05 Fix up some missed "go fmt"
Because of the size of some of these files, automatic format-on-save was
implicitly disabled in my editor, which I didn't notice before committing.
2018-10-16 18:49:20 -07:00
James Bardin
82d2c5b484 core: use absolute address in CloserProvider
Otherwsie relative addresses may collide and close the incorrect
provider.
2018-10-16 18:49:20 -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
91def7b6f6 core: Better failure output for TestContext2Apply_moduleDestroyOrder 2018-10-16 18:49:20 -07:00
Martin Atkins
bab9f7ce09 core: update Stringer implementations for GraphType and walkOperation
These are no longer correct due to the input walk being removed in an
earlier commit.
2018-10-16 18:49:20 -07:00
Martin Atkins
38f37af7e9 core: remove TestContext2Apply_outputInvalid
This was testing that returning a number as an output would be reported as
an error, but that is intentionally allowed now.
2018-10-16 18:49:20 -07:00
Martin Atkins
b4d7882e2f core: Fix TestContextImport_providerVarConfig
I updated the "Variables" map incorrectly in earlier commit 10fe50bbdb
while making bulk updates to get the tests compiling again with the
changed underlying APIs.

The original value here was "bar", incorrectly changed to "foo" in that
commit. Here we return it back to "bar".
2018-10-16 18:49:20 -07:00
James Bardin
6eb897e293 core: attach provisioner schemas in subgraphs
DynamicExpand also needs to add the provisioner schemas to make sure all
references are found in the subgraph.
2018-10-16 18:49:20 -07:00
Martin Atkins
059de66fcc core: Don't save provider input for non-root module
We only support provider input for the root module. This is already
checked in ProviderInput, but was not checked in SetProviderInput. We
can't actually do anything particularly clever with an invalid call here,
but we will at least generate a WARN log to help with debugging.

Also need to update TestBuiltinEvalContextProviderInput to expect this
new behavior of ignoring input for non-root modules.
2018-10-16 18:49:20 -07:00
Martin Atkins
b99b31ebea core: Correct schema for TestContext2Apply_issue5254
This test is now failing due to the fact that WritePlan is currently
disabled pending a rewrite. This will be addressed in a subsequent commit.
2018-10-16 18:49:20 -07:00
Martin Atkins
432331e484 core: Fix TestContext2Refresh_dataState
Now that we fetch schemas during NewContext, we need to configure the
mock GetSchema method before constructing the context.
2018-10-16 18:49:20 -07:00
James Bardin
df2907abb9 core: TestContext2Apply_dataDependsOn 2018-10-16 18:49:20 -07:00
James Bardin
711f305dce core: TestContext2Validate_interpolateMap 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
d3e4565681 core: LoadSchemas must detect provisioners in non-root modules 2018-10-16 18:49:20 -07:00
Martin Atkins
d961b1de1b core: Stop loading provider schema during graph walk
We now fetch all of the necessary schemas during context creation, so we
can just thread that repository of schemas through into EvalContext and
Evaluator and access the schemas as needed without any further fetching.

This requires updating a few tests to have a valid Provider address in
their state objects, because we need that in order to trigger the loading
of the relevant schema.
2018-10-16 18:49:20 -07:00
James Bardin
555cd977f8 core: TestContext2Validate_interpolateMap 2018-10-16 18:49:20 -07:00
Martin Atkins
aa9d88ad3c core: Schema for TestContext2Apply_multiProviderDestroy
This test depends on having a correct schema, so we'll specify the minimum
schema for its fixture inline here rather than using the superset schema
returned by testProvider.
2018-10-16 18:49:20 -07:00