Commit Graph

21858 Commits

Author SHA1 Message Date
Martin Atkins c82e3ec92f core: even more nil checks to catch missing objects
These are all things that ought to be present in normal use but can end up
being nil in incorrect tests. Test debugging is simpler if these things
return errors gracefully, rather than crashing.
2018-10-16 18:46:46 -07:00
Martin Atkins 26c1584317 core: EvalConfigProvider shouldn't crash if its provider isn't set
While there's no good reason for this to happen in practice, it can arise
in tests if mocks aren't set up quite right, and so we'll catch it and
report it nicely to make test debugging a little easier.
2018-10-16 18:46:46 -07:00
Martin Atkins 7dacb6b6a8 core: Don't crash if EvaluateBlock returns nil during validation
There's actually no good reason for this to happen in the normal case, but
it can happen reasonably easy if a test doesn't properly configure the
MockEvalContext, and so having this check here makes test debugging a
little easier.
2018-10-16 18:46:46 -07:00
Martin Atkins 69d2fa0c15 terraform: fix crasher in TestProcessIgnoreChanges
Since this test case is using t.Run, it must be sure to pass the nested
*testing.T over to the testDiffs function or else calls to t.Fatal will
crash the whole test process, since they would otherwise be called on the
wrong instance of *testing.T.
2018-10-16 18:46:46 -07:00
Martin Atkins 0dd7677d1f core: fail gracefully if provider schemas aren't available
The only reason these cases are arising right now is because we have tests
that haven't yet been updated to properly support schema, but it can't
hurt to add some robustness here to reduce the risk of real crashes.
2018-10-16 18:46:46 -07:00
Martin Atkins 5e8445b7a5 addrs: Resource.String shouldn't ever crash
Previously we had a panic in here for invalid resource modes. While that
does always indicate a programming error, it's frustrating to have a
crasher inside a String method since it often impedes our ability to
report an error properly, since the error reporting itself can crash.

Instead we'll just return an invalid string and hope the caller really is
bailing out with an error message.
2018-10-16 18:46:46 -07:00
Martin Atkins c4fac74371 configs: Fix crasher in provider configuration reference parsing
Due to a logic error, this would panic if given an empty traversal.
2018-10-16 18:46:46 -07:00
Martin Atkins cd584309b9 configs: Fix typo in the deprecation warning about ignore_changes = ["*"] 2018-10-16 18:46:46 -07:00
Martin Atkins 4a21b763aa core: Get tests compiling again
After the refactoring to integrate HCL2 many of the tests were no longer
using correct types, attribute names, etc.

This is a bulk update of all of the tests to make them compile again, with
minimal changes otherwise. Although the tests now compile, many of them
do not yet pass. The tests will be gradually repaired in subsequent
commits, as we continue to complete the refactoring and retrofit work.
2018-10-16 18:46:46 -07:00
Martin Atkins 119c80d5e2 addrs: ModuleInstance methods for building AbsProviderConfig
These helpers, similar to other such methods on ModuleInstance, are useful
for programmatically constructing provider config addresses, particularly
in tests where this is more straightforward than parsing from strings.
2018-10-16 18:46:46 -07:00
Martin Atkins 20f6de735d core: Update MockResourceProvisioner to include GetConfigSchema
This method is now required for the ResourceProvisioner interface.
2018-10-16 18:46:46 -07:00
Martin Atkins f085af4ba6 command: update "terraform console" for HCL2
This now uses the HCL2 parser and evaluator APIs and evaluates in terms
of a new-style *lang.Scope, rather than the old terraform.Interpolator
type that is no longer functional.

The Context.Eval method used here behaves differently than the
Context.Interpolater method used previously: it performs a graph walk
to populate transient values such as input variables, local values, and
output values, and produces its scope in terms of the result of that
graph walk. Because of this, it is a lot more robust than the prior method
when asked to resolve references other than those that are persisted
in the state.
2018-10-16 18:46:46 -07:00
Martin Atkins 73053eb5ef core: Context.Eval method
Some of the objects that are referencable from expressions are transient
values computed only during a graph walk, and not persisted in state. In
order to support arbitrary evaluation of expressions, such as in the
"terraform console" CLI command, it's necessary to be able to evaluate
these values before we start evaluating.

This new Eval method achieves this by performing a special graph walk that
ignores resources (except for dependency resolution) and just focuses on
evaluating all of these transient values, before returning an evaluation
scope that can then resolve expressions in terms of that result.

This replaces the Context.Interpolator method, which was fraught with
various issues due to it not properly priming the state before evaluating.
2018-10-16 18:46:46 -07:00
Martin Atkins 630e3b4be2 core: evaluation for HCL2-flavored reference expressions
Here we replace the stub implementations in evaluationStateData with real
implementations that are based on their equivalents in the old
Interpolator type.

The behavior here is a little different due to the different semantics
expected under HCL2, but the principle remains the same: the main
references are resolved from the state, using config for validation
in order to produce some helpful error messages.
2018-10-16 18:46:46 -07:00
Martin Atkins 25e3ac56d2 core: Wire back in module input variables to the evaluator
I took some missteps here while doing the initial refactor for HCL2 types.
This restores the map of maps that retains all of the variable values, and
then makes it available to the evaluator.
2018-10-16 18:46:46 -07:00
Martin Atkins 4b5868f653 core: BuiltinEvalContext constructs evaluationStateData itself
Previously our evaluationStateData object was constructed inside
Evaluator.Scope, but this was awkward because all of the fields inside it
need to be populated from BuiltinEvalContext fields, and so the signature
of Evaluator.Scope kept growing new arguments over time.

Instead, we reassign the responsibilities here so that Evaluator.Scope
takes an already-constructed lang.Data, and then teach BuiltinEvalContext
to build this object itself from its own internal values.
2018-10-16 18:46:46 -07:00
Martin Atkins b0435cd533 core: ProviderConfigTransformer properly locates parent module
Due to a logic error here we were trying to find our our module's parent
as a descendent of itself, rather than as a descendent of the root. It
turns out that we can do this even more simply by just accessing the
Parent field on the given config, avoiding the need to traverse the tree
down from the root at all.

While here, this also switches to using the path.Call helper method rather
than manually slicing the path array, since this better communicates our
intent.
2018-10-16 18:46:46 -07:00
Martin Atkins b9c4780f07 addrs: Helper methods for converting module calls to absolute modules 2018-10-16 18:46:46 -07:00
Martin Atkins c97dd145b9 addrs: Module.Call method
This is a helper for splitting a non-root module path into a callee and
call pair, similar to the method of the same name on ModuleInstance.
2018-10-16 18:46:46 -07:00
Martin Atkins d4cfe85361 core: pass InstanceKey to EvaluateBlock
This gives us the value we need to evaluate a "count.index" reference, and
later also the equivalent for the "for_each" argument once implemented.
2018-10-16 18:46:46 -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 ca67899827 core: NewLegacyResourceInstanceAddress correct handling of addrs.NoKey
Previously we were setting zero here, but the correct way to represent
"no index" in a *ResourceAddress is to set the index to -1.
2018-10-16 18:46:46 -07:00
Martin Atkins a28c93c3ce core: render variables, locals and outputs nicely in "terraform graph" 2018-10-16 18:46:46 -07:00
Martin Atkins 5cf791861f configs: Allow looking up resources by resource addresses.
Throughout the main "terraform" package we identify resources using the
address types, and so this helper is useful to make concise transitions
between the address types and the configuration types.

As part of this, we use the address types to produce the keys used in our
resource maps. This has no visible change in behavior since the prior
implementation produced an equal result, but this change ensures that
ResourceByAddr cannot be broken by hypothetical future changes to the
key serialization.
2018-10-16 18:46:46 -07:00
Martin Atkins ccc1b6990f config/hcl2shim: shims from flatmap to cty and vice-versa
These particular shims will have a pretty limited lifetime in mainline
Terraform code (primarily to stub out the new expression evaluator against
the old state structs until the new format is implemented) but will live
on for some time in state migration and provider plugin compatibility
shims.
2018-10-16 18:46:46 -07:00
Martin Atkins 9ca13d5c1d command/validate: make sure diagnostics is always present and an array
Previously an empty diagnostics would appear as "null" in the JSON output,
since that is how encoding/json serializes a nil slice. It's more
convenient for users of dynamic languages to keep the type consistent
in all cases, since they can then just iterate the list without needing a
special case for when it is null.
2018-10-16 18:46:46 -07:00
Martin Atkins 70f1635416 configs: record the source directory for modules
We can only do this when modules are loaded with Parser.LoadConfigDir,
but in practice this is the common case anyway.

This is important to support the path.module and path.root expressions in
configuration.
2018-10-16 18:46:46 -07:00
Martin Atkins fa2a76fa23 configs: use addrs.Module for module path, rather than []string
addrs.Module is itself internally just []string, but this better
communicates our intent here and makes this integrate better with other
code which is using this type for this purposes.
2018-10-16 18:46:46 -07:00
Martin Atkins 226d66bac8 core: include "root" element when constructing legacy ModuleState path
We've not yet adjusted any of the state structs to reflect our new address
types because they are used with encoding/json to produce our state file
format, but the shimming here previously was incorrect because it failed
to include the special "root" string that's always required at element
zero of a module path in the state.
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
Martin Atkins 2c70d884d6 dag: node visits return diagnostics rather than errors
This allows node visits to also return warnings.
2018-10-16 18:44:26 -07:00
Martin Atkins 24dce0c624 configs: Helper methods to integrate with "addrs" package
Our new "addrs" package gives us some nice representations of various
kinds of "address" within Terraform. To talk to APIs that use these, it's
convenient to be able to easily derive such addresses from the
configuration objects.

These new methods, along with a recasting of the existing
Resource.ProviderConfigKey method to Resource.ProviderConfigAddr, give us
some key integration points to support the configuration graph transforms
in the main "terraform" package.
2018-10-16 18:44:26 -07:00
Martin Atkins 072322336e addrs: AbsProviderConfig.Inherited method
This helper deals with the address wrangling required to find the address
that a provider configuration might inherit from if no explicit
configuration is given and instead configuration is taken from the
parent module.

This method is not generally useful, and is here mainly just to help the
provider-related graph transformations in the main terraform package.
2018-10-16 18:44:26 -07:00
Martin Atkins 02b25e7057 addrs: flesh out functionality ready to replace terraform.ResourceAddress
This "kitchen sink" commit is mainly focused on supporting "targets" as
a new sub-category of addresses, for use-case like the -target CLI option,
but also includes some other functionality to get closer to replacing
terraform.ResourceAddress and fill out some missing parts for representing
various other address types that are currently represented as strings
in the "terraform" package.
2018-10-16 18:44:26 -07:00
Martin Atkins b6fdd0446e configs: parse the "providers" map for module calls
This was accidentally missed on the first pass of module call decoding.
As before, this is a map from child provider config address to parent
provider config address, allowing the set of providers to be projected in
arbitrary ways into a child module.
2018-10-16 18:44:26 -07:00
Martin Atkins c6598a3f86 addrs: ParseAbsProviderConfig function
This is for parsing the type of provider configuration address we write
into state in order to remember which provider configuration is
responsible for each resource.
2018-10-16 18:44:26 -07:00
Martin Atkins 8ca174b133 addrs: implement String for AbsResource and AbsResourceInstance 2018-10-16 18:44:26 -07:00
Martin Atkins a09498a8a3 core: load a provider's schema at initialization
This is currently not very ergonomic due to the API exposed by providers.
We'll smooth this out in a later change to improve the provider API, since
we know we always want the entire schema.
2018-10-16 18:44:26 -07:00
Martin Atkins 3822650e15 tfdiags: Diagnostics.ErrWithWarnings and .NonFatalErr
There is some existing practice in the "terraform" package of returning
a special error type ValidationError from EvalNode implementations in
order to return warnings without halting the graph walk even though a
non-nil error was returned.

This is a diagnostics-flavored version of that approach, allowing us to
avoid totally reworking the EvalNode concept around diagnostics and
retaining the ability to return non-fatal errors.

NonFatalErr is equivalent to the former terraform.ValidationError, while
ErrWithWarnings is a helper that automatically treats any errors as
fatal but returns NonFatalError if the diagnostics contains only warnings.
2018-10-16 18:44:26 -07:00
Martin Atkins fca07d1a61 addrs: AbsProviderConfig type
Fitting with the usual naming scheme, this is the combination of a
module instance address and a provider config.
2018-10-16 18:44:26 -07:00
Martin Atkins dd62cd97c9 configs: DisabledModuleWalker
This is a built-in implementation of ModuleWalker that just returns an
error any time it's asked for a module. This is intended for simple unit
tests where no child modules are needed anyway.
2018-10-16 18:44:26 -07:00
Martin Atkins 2eba023537 configs: NewEmptyConfig function
This is useful for creating a valid placeholder configuration, but not
much else. Most callers should use BuildConfig to build a configuration
that actually has something in it.
2018-10-16 18:44:26 -07:00
Martin Atkins c07b0a7806 configs: Re-unify the ManagedResource and DataResource types
Initially the intent here was to tease these apart a little more since
they don't really share much behavior in common in core, but in practice
it'll take a lot of refactoring to tease apart these assumptions in core
right now and so we'll keep these things unified at the configuration
layer in the interests of minimizing disruption at the core layer.

The two types are still kept in separate maps to help reinforce the fact
that they are separate concepts with some behaviors in common, rather than
the same concept.
2018-10-16 18:44:26 -07:00
Martin Atkins cd51864d84 configs: Start using the new "addrs" package types for modules
We initially just mimicked our old practice of using []string for module
paths here, but the addrs package now gives us a pair of types that better
capture the two different kinds of module addresses we are dealing with:
static addresses (nodes in the configuration tree) and dynamic/instance
addresses (which can represent the situation where multiple instances are
created from a single module call).

This distinction still remains rather artificial since we don't yet have
support for count or for_each on module calls, but this is intended to lay
the foundations for that to be added later, and in the mean time just
gives us some handy helper functions for parsing and formatting these
address types.
2018-10-16 18:44:26 -07:00
Martin Atkins a16ca2ec53 lang: new package for the runtime parts of the config language
Whereas package "configs" deals with the static structure of the
configuration language, this new package "lang" deals with the dynamic
aspects such as expression evaluation.

So far this mainly consists of populating a hcl.EvalContext that contains
the values necessary to evaluate a block or an expression. There is also
special handling here for dynamic block generation using the HCL
"dynblock" extension, which is exposed in the public interface (rather
than hiding it as an implementation detail of EvalBlock) so that the
caller can then extract proper source locations for any result values
using the expanded body.

This also includes the beginnings of a replacement for the function table
handling that currently lives in the old "config" package, but most of
the functions are not yet ported and so this will expand in subsequent
commits.
2018-10-16 18:44:26 -07:00
Martin Atkins e5dfa17433 addrs: All Referenceable implementations support String()
This gives us a convenient way to convert back to a string representation
that matches what the user would've written in configuration.
2018-10-16 18:44:26 -07:00
Martin Atkins f2809854a2 govendor fetch github.com/hashicorp/hcl2/ext/dynblock/... 2018-10-16 18:44:26 -07:00
Martin Atkins 63041ffa09 addrs: ParseRef function, for parsing references in expressions
This function corresponds to terraform.NewInterpolatedVariable, but built
with HCL2 primitives. It accepts a hcl.Traversal, which is what is
returned from the HCL2 API functions to find which variables are
referenced in a given expression.
2018-10-16 18:44:26 -07:00
Martin Atkins b9d84f2944 addrs: new package for representing addresses
This package is intended to contain all the functionality for parsing,
representing, and formatting addresses of objects within Terraform.

It will eventually subsume the responsibilities of both the
InterpolatedVariable and ResourceAddress types in the "terraform" package,
but for the moment is just a set of types for representing these things,
lacking any way to parse or format them. The remaining functionality
will follow in subsequent commits.
2018-10-16 18:44:26 -07:00
Martin Atkins 4ed06a9227 terraform: HCL2-flavored module dependency resolver
For the moment this is just a lightly-adapted copy of
ModuleTreeDependencies named ConfigTreeDependencies, with the goal that
the two can live concurrently for the moment while not all callers are yet
updated and then we can drop ModuleTreeDependencies and its helper
functions altogether in a later commit.

This can then be used to make "terraform init" and "terraform providers"
work properly with the HCL2-powered configuration loader.
2018-10-16 18:44:26 -07:00