Previously we were using the experimental HCL 2 repository, but now we'll
shift over to the v2 import path within the main HCL repository as part of
actually releasing HCL 2.0 as stable.
This is a mechanical search/replace to the new import paths. It also
switches to the v2.0.0 release of HCL, which includes some new code that
Terraform didn't previously have but should not change any behavior that
matters for Terraform's purposes.
For the moment the experimental HCL2 repository is still an indirect
dependency via terraform-config-inspect, so it remains in our go.sum and
vendor directories for the moment. Because terraform-config-inspect uses
a much smaller subset of the HCL2 functionality, this does still manage
to prune the vendor directory a little. A subsequent release of
terraform-config-inspect should allow us to completely remove that old
repository in a future commit.
* command/import: properly use `-provider` supplied on the command line
The import command now attaches the provider configuration in the resource
instance, if set. That config is attached to the NodeAbstractResource
during the import graph building. This prevents errors when the implied
provider is not actually in the configuration at all, which may happen
when a configuration is using the `-beta` version of a provider (and
only that `-beta` version).
* command/import: fix variable reassignment and update docs
Fixes#22564
This was a vestige from earlier prototyping when we were considering
supporting adding credentials to existing .tfrc native syntax files.
However, that proved impractical because the CLI config format is still
HCL 1.0 and that can't reliably perform programmatic surgical updates,
so we'll remove this option for now. We might add it back in later if it
becomes more practical to support it.
These run against a stub OAuth server implementation, verifying that we
are able to run an end-to-end login transaction for both the authorization
code and the password grant types.
This includes adding support for authorization code grants to our stub
OAuth server implementation; it previously supported only the password
grant type.
For unit testing in particular we can't launch a real browser for testing,
so this indirection is primarily to allow us to substitute a mock when
testing a command that can launch a browser.
This includes a simple mock implementation that expects to interact with
a running web server directly.
Because we're going to pass the credentials we obtain on to some
credentials store (either a credentials helper or a local file on disk)
we ought to disclose that first and give the user a chance to cancel out
and set up a different credentials storage mechanism first if desired.
This also includes the very beginnings of support for the owner password
grant type when running against app.terraform.io. This will be used only
temporarily at initial release to allow a faster initial release without
blocking on implementation of a full OAuth flow in Terraform Cloud.
The canonical location of the "template" provider is now in the hashicorp
namespace rather than the terraform-providers namespace, so the output
has changed to reflect that.
A more convenient interface to get a throwaway empty credentials source
for use in tests, which doesn't interact at all with the real CLI
configuration directory.
Previously `terraform console` would output an `init required` error if
it was run in a directory originally `init`ed with a `-plugin-dir`
specified.
Fixes#17826
This was a leftover from the migration of these types from the main
package, but we don't actually need or want this here because this
particular detail is still handled by the main package, and because the
cliconfig package must not depend on the command package in order to avoid
an import cycle.
This new implementation is not yet used, but should eventually replace the
technique of composing together various types from the svchost/auth
package, since our requirements are now complex enough that they're more
straightforward to express in direct code within a single type than as
a composition of the building blocks in the svchost/auth package.
Any command using meta.defaultFlagSet *might* occasionally exit before
the flag package's output got written. This caused flag error messages
to get lost. This PR discards the flag package output in favor of
directly returning the error to the end user.
Create the missing modules in the state when moving resources to a
module that doesn't yet exist. This allows for refactoring of
configuration into new modules, without having to create dummy resources
in the module before the "state mv" operations.
This is just a wholesale move of the CLI configuration types and functions
from the main package into its own package, leaving behind some type
aliases and wrappers for now to keep existing callers working.
This commit alone doesn't really achieve anything, but in future commits
we'll expand the functionality in this package.
* command/init: omit a warning if -backend-config is used with no backend
block
Terraform would silently accept - and swallow - `-backend-config` on the
CLI when there was no `backend` block. Since it is mostly expected to
override existing backend configuration, terraform
should omit a warning if there is no backend configuration to
override.
If the user intended to override the default (local) backend
configuration, they can first add a `backend` block to the `terraform` block to silence the warning (or just ignore it):
```hcl
terraform {
backend "local" {}
}
```
One of the show json command tests expected no error when presented with
an invalid configuration in a nested module. Modify the test created in
PR #21569 so that it can still verify there is no panic, but now expect
an error from init.
We always add an empty line when asking/checking the version. We should only do
that if there is a new version available. While this is purely cosmetic, it
reads better and is consistent with packer.
This includes a fix to make sure that an expression with a static string
index, like foo["bar"], will be parsed as a traversal rather than as a
dynamic index expression.
* command/show: marshal the state snapshot from the planfile
The planfile contains a state snapshot with certain resources updated
(outputs and datasources). Previously `terraform show -json PLANFILE`
was using the current state instead of the state inside the plan as
intended.
This caused an issue when the state included a terraform_remote_state
datasource. The datasource's state gets refreshed - and therefore
upgraded to the current state version - during plan, but that won't
persist to state until apply.
* update comment to reflect new return
In the unlikely event that a moduleCall has a nil config - for example,
if a nested module call includes a variable with a typo in an
attribute - continue gracefully.
* command/show -json: fix panic
afterUnknown should return only bools, not values.
* command/jsonplan: let's delete some redundant code!
the plan output was somewhat inconsistent with return values for
"after_unknown". This strives to fix that. If all "after" values are
known, return an empty object instead of iterating over values.
Also fixing some typos and general copypasta.
There is currently no way to unset -backend-config during init, since
not setting that option assumes the user will use the saved config.
Allow setting `-backend-config=""` to specify no overrides.
The omitUnknowns and unknownAsBool functions were previously trying hard
to preserve the same collection types in the output as they had in the
input, by attempting to keep everything matched up so that the results
would be valid.
Unfortunately, this turns out to be a harder problem than we originally
thought: it was possible for a collection value going in to produce
inconsistent element types out (and thus a panic) in the following
situations:
- when a collection with mixed known and unknown values was passed in
to omitUnknowns.
- when a collection of collections where the inner collections are a
mixture of empty and not empty in unknownAsNull.
The results of these functions are only used to marshal to JSON anyway,
and JSON serialization can't distinguish between the three sequence types
or the two mapping types, so in practice we can just standardize on
converting all sequences to tuple and all mappings to object here and not
change the resulting output at all, and then we don't have to worry about
making sure all of the inner types get preserved exactly.
A nice consequence of that relaxation is that we can now do what we
originally wanted to do with unknownAsBool, and omit map keys and
object attributes altogether if their values would've been false,
producing a much more compact result. This is easiest to do now when
there's only one known user of this JSON plan output, and we know that
user will treat both false and omitted as the same here.
The backend gets to "prepare" the configuration before Configure is
called, in order to validate the values and insert defaults. We don't
want to store this value in the "config state", because it will often
not match the raw config after it is prepared, forcing unecessary
backend migrations during init.
Since PrepareConfig is always called before Configure, we can store the
config value directly, and assume that it will be prepared in the same
manner each time.
If the backend config hashes match during init, and there are no new
backend override options, then we assume the existing config is OK.
Since init should be idempotent, we should be able to run init with no
options or config changes, and not effect the backends at all.
This includes a small fix to ensure the parser doesn't produce an invalid
body for block parsing syntax errors, and instead produces an incomplete
result that calling applications like Terraform can still analyze.
The problem here was affecting our version-constraint-sniffing code, which
intentionally tried to find a core version constraint even if there's a
syntax error so that it can report that a new version of Terraform is a
likely cause of the syntax error. It was working in most cases, unless
it was the "terraform" block itself that contained the error, because then
we'd try to analyze a broken hcl.Block with a nil body.
This includes a new test for "terraform init" that exercises this
recovery codepath.
There are a number of use cases that can require a user to select a workspace after initializing Terraform.
To make sure we cover all these use cases, we will always call the selectWorkspace method to verify a valid workspace is already selected or (if needed) offer to select one before moving on.
cty now guarantees that sets of primitive values will iterate in a
reasonable order. Previously it was the caller's responsibility to deal
with that, but we invariably neglected to do so, causing inconsistent
ordering. Since cty prioritizes consistent behavior over performance, it
now imposes its own sort on set elements as part of iterating over them so
that calling applications don't have to worry so much about it.
This change also causes cty to consistently push unknown and null values
in sets to the end of iteration, where before that was undefined. This
means that our diff output will now consistently list additions before
removals when showing sets, rather than the ordering being undefined as
before.
The ordering of known, non-null, non-primitive values is still not
contractually fixed but remains consistent for a particular version of
cty.
* internal/initwd: Allow deprecated relative module paths
In Terraform 0.11 we deprecated this form but didn't have any explicit
warning for it. Now we'll still accept it but generate a warning. In a
future major release we will drop this form altogether, since it is
ambiguous with registry module source addresses.
This codepath is covered by the command/e2etest suite.
* e2e: Skip copying .exists file, if present
We use this only in the "empty" test fixture in order to let git know that
the directory exists. We need to skip copying it so that we can test
"terraform init -from-module=...", which expects to find an empty
directory.
* command/e2etests: Re-enable and fix up the e2etest "acctests"
We disabled all of the tests that accessed remote services like the
Terraform Registry while they were being updated to support the new
protocols we now expect. With those services now in place, we can
re-enable these tests.
Some details of exactly what output we print, etc, have intentionally
changed since these tests were last updated.
* e2e: refactor for modern states and plans
* command/e2etest: re-enable e2etests and update for tf 0.12 compatibility
plugin/discovery: mkdirAll instead of mkdir when creating cache dir
Once you start reading from stdin, that is a blocking call that will
never finish. So when a context is canceled causing the input method to
return, the read will remain blocking in the running goroutine.
There isn't a real solution for it (e.g. its not possible to unblock the
read) so the only solution is to make the reader reusable.
When rendering the diff, the NoOp changes should come from the LCS
sequence, rather than the new sequence. The two indexes will not align
in many cases, adding the wrong new object or indexing out of bounds.
* command/state_list.go: fix bug loading user-defined state
If the user supplied a state path via the `-state` flag and terraform
was running in a workspace other than `default`, the state was not being
loaded properly. Fixes#19920
In study of existing providers we've found a pattern we werent previously
accounting for of using a nested block type to represent a group of
arguments that relate to a particular feature that is always enabled but
where it improves configuration readability to group all of its settings
together in a nested block.
The existing NestingSingle was not a good fit for this because it is
designed under the assumption that the presence or absence of the block
has some significance in enabling or disabling the relevant feature, and
so for these always-active cases we'd generate a misleading plan where
the settings for the feature appear totally absent, rather than showing
the default values that will be selected.
NestingGroup is, therefore, a slight variation of NestingSingle where
presence vs. absence of the block is not distinguishable (it's never null)
and instead its contents are treated as unset when the block is absent.
This then in turn causes any default values associated with the nested
arguments to be honored and displayed in the plan whenever the block is
not explicitly configured.
The current SDK cannot activate this mode, but that's okay because its
"legacy type system" opt-out flag allows it to force a block to be
processed in this way anyway. We're adding this now so that we can
introduce the feature in a future SDK without causing a breaking change
to the protocol, since the set of possible block nesting modes is not
extensible.
If the registry is unresponsive, you will now get an error
specific to this, rather than a misleading "provider unavailable" type
error. Also adds debug logging for when errors like this may occur
Due to these tests happening in the wrong order, removing an object from
the end of a sequence of objects would previously cause a bounds-check
panic.
Rather than a more severe rework of the logic here, for now we'll just
introduce an extra precondition to prevent the panic. The code that
follows already handles the case where there _is_ no new object (i.e. the
"old" object is being deleted) as long as we're able to pass through this
type-checking logic.
The new "JSON list of objects - removing item" test covers this problem
by rendering a diff for an object being removed from the end of a list
of objects within a JSON value.
Terraform Registry (and other registry implementations) can now return
an array of warnings with the versions response. These warnings are now
displayed to the user during a `terraform init`.
In earlier refactoring we updated these commands to support the new
address and state types, but attempted to partially retain the old-style
"StateFilter" abstraction that originally lived in the Terraform package,
even though that was no longer being used for any other functionality.
Unfortunately the adaptation of the existing filtering to the new types
wasn't exact and so these commands ended up having a few bugs that were
not covered by the existing tests.
Since the old StateFilter behavior was the source of various misbehavior
anyway, here it's removed altogether and replaced with some simpler
functions in the state_meta.go file that are tailored to the use-cases of
these sub-commands.
As well as just generally behaving more consistently with the other
parts of Terraform that use the new resource address types, this commit
fixes the following bugs:
- A resource address of aws_instance.foo would previously match an
resource of that type and name in any module, which disagreed with the
expected interpretation elsewhere of meaning a single resource in the
root module.
- The "terraform state mv" command was not supporting moves from a single
resource address to an indexed address and vice-versa, because the old
logic didn't need to make that distinction while they are two separate
address types in the new logic. Now we allow resources that do not have
count/for_each to be treated as if they are instances for the purposes
of this command, which is a better match for likely user intent and for
the old behavior.
Finally, we also clean up a little some of the usage output from these
commands, which hasn't been updated for some time and so had both some
stale information and some inaccurate terminology.
* command/providers schemas: return empty json object if config parses successfully but no providers found
* command/show (state): return an empty object if state is nil
* configs/configupgrade: detect possible relative module sources
If a module source appears to be a relative local path but does not have
a preceding ./, print a #TODO message for the user.
* internal/initwd: limit go-getter detectors to those supported by terraform
* internal/initwd: move isMaybeRelativeLocalPath check into getWithGoGetter
To avoid making two calls to getter.Detect, which potentially makes
non-trivial API calls, the "isMaybeRelativeLocalPath" check was moved to
a later step and a custom error type was added so user-friendly
diagnostics could be displayed in the event that a possible relative local
path was detected.
Our initial prototype of new-style diff rendering excluded this because
the old SDK has no support for this construct. However, we want to be able
to introduce this construct in the new SDK without breaking compatibility
with existing versions of Terraform Core, so we need to implement it now
so it's ready to be used once the SDK implements it.
The key associated with each block allows us to properly correlate the
items to recognize the difference between an in-place update of an
existing block and the addition/deletion of a block.
Our null-to-empty normalization was previously assuming these would always
be collection types, but that isn't true when a block contains something
dynamic since we must then use tuple or object types instead to properly
represent all of the individual element types.
We use cty a little differently when a nested list block contains a
dynamically-typed attribute: it appears as a tuple value instead of a
list value so that we can retain the individual types of each element.
Here we introduce a test for that case, but doing so required also making
the runTestCases function handle types in a stricter way so that it will
produce planned values that match how Terraform Core would do it,
including the necessary late-bound type information for the
dynamically-typed attribute.