When configuration is read out of JSON, HCL assumes that empty levels of
objects can be flattened, but this removes too much to decode into a
config.Terraform struct.
Reconstruct the appropriate AST to decode the config struct.
Ensure that fields set in an earlier Terraform config block aren't
removed by Append when encountering another Terraform block. When
multiple blocks contain the same field, the later one still wins.
Fixes#12788
We would panic when referencing an output from an undefined module. The
panic above this is correct but in this case Load will not catch
interpolated variables that _reference_ an unloaded/undefined module.
Test included.
It can be tedious fixing a new module with many errors when Terraform
only outputs the first random error it encounters.
Accumulate all errors from validation, and format them for the user.
Fixes#11800
Type check the value of count so we don't panic on the conversion.
I wondered "why didn't we do this before?" There is no excuse for NOT
doing it at all but the reasoning was beacuse prior to the list/map work
in 0.7, the value couldn't be anything other than a string since any
primitive can turn into a string.
Regardless, we should've always done this.
This disables the computed value check for `count` during the validation
pass. This enables partial support for #3888 or #1497: as long as the
value is non-computed during the plan, complex values will work in
counts.
**Notably, this allows data source values to be present in counts!**
The "count" value can be disabled during validation safely because we
can treat it as if any field that uses `count.index` is computed for
validation. We then validate a single instance (as if `count = 1`) just
to make sure all required fields are set.
Fixes#11038
This is a **short term fix**.
Terraform core doesn't currently handle root modules named "root" well
because the prefix `[]string{"root"}` has special meaning and Terraform
core [currently] can't disambiguate between the root module and a module
named "root" in the root module.
This PR introduces a short term fix by simply disallowing root modules
named "root". This shouldn't break any BC because since 0.8.0 this
didn't work at all in many broken ways (including crashes).
Longer term, this should be fixed by removing the special prefix at all
and having empty paths be root. I started down this path but the core
changes necessary are far too scary for a patch release. We can aim for
0.9.
Fixes#4789
This improves the validation that valid provider aliases are used.
Previously, we required that provider aliases be defined in every module
they're used. This isn't correct because the alias may be used in a
parent module and inherited.
This removes that validation and creates the validation that a provider
alias must be defined in the used module or _any parent_. This allows
inheritance to work properly.
We've always had this type of validation for aliases because we believe
its a good UX tradeoff: typo-ing an alias is really painful, so we
require declaration of alias usage. It may add a small burden to
declare, but since relatively few aliases are used, it improves the
scenario where a user fat-fingers an alias name.
Fixes#10715
`config.Merge` was not updated to support a number of new features. This
updates the codepath to merge various fields, including the `terraform`
block which was the issue in #10715.
The `Merge` API is called when an `_override` file is present to _merge_
configurations. Normally configurations are _appended_. Only an override
file triggers a _merge_.
I started working on a generic library to do this automatically awhile
back but never finished it. This might motivate me to do so. In the
interest of getting a fix out though, we'll continue the manual
approach.
Fixes#10597
This disallows any names for variables, modules, etc. starting with
ints. This causes parse errors with the new HIL parser and actually
causes long term ambiguities if we allow this.
I've also updated the upgrade guide to note this as a backwards
compatibility and how people can fix this going forward.
We allow variables to have descriptions specified, as additional context
for a module user as to what should be provided for a given variable.
We previously lacked a similar mechanism for outputs. Since they too are
part of a module's public interface, it makes sense to be able to add
descriptions for these for symmetry's sake.
This change makes a "description" attribute valid within an "output"
configuration block and stores it within the configuration data structure,
but doesn't yet do anything further with it. For now this is useful only
for third-party tools that might parse a module's config to generate
user documentation; later we could expose the descriptions as part of
the "apply" output, but that is left for a separate change.
Fixes#10075Fixes#10013
When interpolating, we were only maintaining the last known slice index.
If you had sibling slices then you could lose your slice index when
exiting the slice. The resulting behavior was that no some runs the
computed key would be: "slice.0.attr" and on others would be
"slice.attr", the latter being incorrect.
We now maintain a list of slice indexes so that as we unnest, we
properly restore the old value.
Surprisingly unrelated to the graph but the shadow graph caught this
which is great. :)
Fixes#7774
This modifies the `import` command to load configuration files from the
pwd. This also augments the configuration loading section for the CLI to
have a new option (default false, same as old behavior) to
allow directories with no Terraform configurations.
For import, we allow directories with no Terraform configurations so
this option is set to true.
Fixes#7846
This changes from using the HCL decoder to manually decoding the
`variable` blocks within the configuration. This gives us a lot more
power to catch validation errors. This PR retains the same tests and
fixes one additional issue (covered by a test) in the case where a
variable has no named assigned.
Fixes#7607
An empty list is a valid value for formatlist which means to just return
an empty list as a result. The logic was somewhat convoluted here so I
cleaned that up a bit too. The function overall can definitely be
cleaned up a lot more but I left it mostly as-is to fix the bug.
This commit adds a new interpolation function, zipmap, which produces a
map given a list of string keys and a list of values of the same length
as the list of keys.
The name comes from the same operation in Clojure (and likely other
functional langauges).
This is the limitation of all lifecycle attributes currently. Right now,
interpolations are allowed through and the user ends up thinking it
should work. We should give an error.
In the future it should be possible to support some minimal set of
interpolations (static variables, data sources even perhaps) but for now
let's validate that this doesn't work.
This changes the key for the storage to be the _raw_ source from the
module, not the fully expanded source. Example: it'll be a relative path
instead of an absolute path.
This allows the ".terraform/modules" directory to be portable when
moving to other machines. This was a behavior that existed in <= 0.7.2
and was broken with #8398. This amends that and adds a test to verify.
As part of working on ResourceConfig.DeepCopy, Equal I updated
reflectwalk (to fix some issues in the new functions) but this
introduced more issues in other parts of Terraform. This update fixes
those.
Data sources should be able to support counts like a resource. We need
to remove "count" when we load the config because the key doesn't exist
in the schema, and the resource won't validate.
When a resource has only a single key set, the HCL parser treats that
key as part of the overall set of object keys. This isn't valid since
we expect resources to have exactly two keys. In this scenario, we have
to "unwrap" the keys back into a set of objects.
Set the default log package output to iotuil.Discard during tests if the
`-v` flag isn't set. If we are verbose, then apply the filter according
to the TF_LOG env variable.
The concat interpolation function now only accepts list arguments.
Strings are no longer supported, for concatenation or appending to
lists. All arguments must be a list, and single elements can be promoted
with the `list` interpolation function.
Fixes the following error when cross compiling:
```
--> freebsd/amd64 error: exit status 2
Stderr: # github.com/hashicorp/terraform/config/module
config/module/inode.go:18: cannot use st.Ino (type uint32) as type uint64 in return argument
```
* `map(key, value, ...)` - Returns a map consisting of the key/value pairs
specified as arguments. Every odd argument must be a string key, and every
even argument must have the same type as the other values specified.
Duplicate keys are not allowed. Examples:
* `map("hello", "world")`
* `map("us-east", list("a", "b", "c"), "us-west", list("b", "c", "d"))`
This will allow the concat interpolation function to accept lists of
lists, and lists of maps as well as strings. We still allow bare strings
for backwards compatibility, but remove some of the old comment wording
as it could cause confusion of this function with actual string
concatenation.
Since maps are now supported in the config, this removes the superfluous
(and failing) TestInterpolationFuncConcatListOfMaps.
Allow lists and maps within the list interpolation function via variable
interpolation. Since this requires setting the variadic type to TypeAny,
we check for non-heterogeneous lists in the callback.
The list() interpolation function provides a way to add support for list
literals (of strings) to HIL without having to invent new syntax for it
and modify the HIL parser.
It presents as a function, thus:
- list() -> []
- list("a") -> ["a"]
- list("a", "b") -> ["a", "b"]
Thanks to @wr0ngway for the idea of this approach, fixes#7460.
Part of the interpolation walk is to detect keys which involve computed
values and therefore cannot be resolved at this time. The interplation
walker keeps sufficient state to be able to populate the ResourceConfig
with a slice of such keys.
Previously they didn't take slice indexes into account, so in the
following case:
```
"services": []interface{}{
map[string]interface{}{
"elb": "___something computed___",
},
map[string]interface{}{
"elb": "___something else computed___",
},
map[string]interface{}{
"elb": "not computed",
},
}
```
Unknown keys would be populated as follows:
```
services.elb
services.elb
```
This is not sufficient information to be useful, as it is impossible to
distinguish which of the `services.elb`s are unknown vs not.
This commit therefore retains the slice indexes as part of the key for
unknown keys - producing for the example above:
```
services.0.elb
services.1.elb
```