We previously used a loader -> BuildConfig flow to load configuration.
This commit changes most (but not all yet) flows to use the new
graph-based approach. Instead of simply recursively loading the modules,
we now need to take a stepped approach:
1. Load the root module
2. Collect the variables and their values
3. Build the configuration with the graph-based approach
Because this approach relies on different parts from different packages,
it can't easliy be done within the `configload` package. So, now we do
most of in the backend or command.
* Implement ReadStateBytes + WriteStateBytes
* [WIP] - Testing ReadStateBytes and WriteStateBytes (#37464)
* Fix nil pointer error
* Add WIP test for ReadStateBytes
* Move test mock to separate testing file
* Update mock to send unexpected EOF when there's a problem returning data and it's not a true EOF
* Add test case for when length != expected length
* Add test for when trying to read state from a store type that doesn't exist
* Change symbol names to lowercase
* Add ability to force a diagnostic to be returned from `mockReadStateBytesClient`'s `Recv` method
* Add test showing error diagnostics raised by the ReadStateBytes client are returned
* Add missing header
* Simplify mock by using an embedded type
* Rename `mockOpts` to `mockReadStateBytesOpts`
* Update existing tests to assert what arguments are passed to the RPC method call
* Add mock WriteStateBytesClient which uses `go.uber.org/mock/gomock` to enable assertions about calls to Send
* Add a test for WriteStateBytes that makes assertions about calls to the Send method
* Update test case to explicitly test writing data smaller than the chunk size
* Implement chunking in WriteStateBytes, add test case to assert expected chunking behaviour
* Add generated mock for Provider_WriteStateBytesClient in protocol v6
* Update tests to use new `MockProvider_WriteStateBytesClient`, remove handwritten mock
* Update code comments in test
* Add tests for diagnostics and errors returned during WriteStateBytes
* Add generated mock for Provider_ReadStateBytesClient in protocol v6, replace old mock
* Add test case for grpc errors in ReadStateBytes, fix how error is returned
* Typo in comment
* Add missing warning test, rename some test cases
* Update proto file definition of Read/WriteStateBytes RPCs (#37529)
* Update Read/WriteStateBytes RPCs to match https://github.com/hashicorp/terraform-plugin-go/pull/531
* Run `make protobuf`
* Run `make generate`
* Update use of `proto.ReadStateBytes_ResponseChunk` in tests
* Fix how diagnostics are handled alongside EOF error, update ReadStateBytes test
* More fixes - test setup was incorrect
I think? I assume that a response would be returned full of zero-values when EOF is encountered.
* WIP - avoid crash if chunk is nil
* Sarah's updates to radek/pss-read-write (#37642)
* Update code to not expect a chunk when EOF encountered
* Return early if any grpc errors are encountered during ReadStateBytes
* Close the stream with CloseSend once everything's read without error. Add test case about handling grpc errors from CloseSend.
* Fix test case about warnings: We would expect to receive a chunk with data alongside the warning and have a normal closing of the stream after EOF
* Add log line, remove unneeded type info
* Implement configurable state chunk size
* handle metadata in WriteStateBytes correctly
* validate chunk sizes received from provider
* ReadStateBytes: avoid early return on warnings
---------
Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com>
* Add ValidateActionConfig to provider interface and protocol
* Update internal/provider-simple-v6/provider.go
Co-authored-by: Daniel Schmidt <danielmschmidt92@gmail.com>
---------
Co-authored-by: Daniel Schmidt <danielmschmidt92@gmail.com>
* Add GetStates RPC method to Plugin Protocol v6
* Add DeleteState RPC method to Plugin Protocol v6
* Add methods to provider-simple
* Fix error messages
* Apply suggestions from code review
Co-authored-by: Radek Simko <radeksimko@users.noreply.github.com>
* Change how GetStates RPC returns the list of state names
* Change GetStates implementation to use new data type
* `make protobuf` to accommodate new code comments
---------
Co-authored-by: Radek Simko <radeksimko@users.noreply.github.com>
* Implement ListResource RPC via callbacks
* Implement ListResource with iterators
* Change `ListResourceResponse` to slice
* Turn ListResourceResponse into a struct
* Add a limit for ListResource
* explicitly cancel stream when listing resources
---------
Co-authored-by: Samsondeen Dare <samsondeen.dare@hashicorp.com>
* Minor auto-formatting changes
* Add list RPC and schema protobuf definitions
* make protobuf
* make generate
* Add ValidateListResourceConfig implementation
* Use different summaries when reporting errors about non-null write-only attribute values
* Refactor `ValidateWriteOnlyAttributes` to use custom details for diagnostics
* Update affected unit tests
* Add change file
This change ensures that providers receive the source private state and can store potentially differing private state as part of a move, rather than always copying the source private state to the target. This functionality has not yet been released and therefore there are no compatibility concerns.
* terraform: remove redundant code
NodeDestroyResourceInstance is never instantiated with a DeposedKey of anything other than states.NotDeposed, so the deleted code is never run. Deposed objects get a NodeDestroyDeposedResourceInstanceObject instead.
* tfdiags: add helper func
* configs: introduce removed block type
* terraform: add forget action
* renderer: render forget actions
* terraform: deposed objects can be forgotten
Deposed objects encountered during planning spawn
NodePlanDeposedResourceInstanceObject, which previously generated a
destroy change. Now it will generate a forget change if the deposed
object is a forget target, and a destroy change otherwise.
The apply graph gains a new node type,
NodeForgetDeposedResourceInstanceObject, whose execution simply removes
the object from the state.
* configs: add RemoveTarget address type
* terraform: modules can be forgotten
* terraform: error if removed obj still in config
* tests: better error on restore state fail
* Update CHANGELOG.md
This is a mostly mechanical refactor with a handful of changes which
are necessary due to the semantic difference between earlyconfig and
configs.
When parsing root and descendant modules in the module installer, we now
check the core version requirements inline. If the Terraform version is
incompatible, we drop any other module loader diagnostics. This ensures
that future language additions don't clutter the output and confuse the
user.
We also add two new checks during the module load process:
* Don't try to load a module with a `nil` source address. This is a
necessary change due to the move away from earlyconfig.
* Don't try to load a module with a blank name (i.e. `module ""`).
Because our module loading manifest uses the stringified module path
as its map key, this causes a collision with the root module, and a
later panic. This is the bug which triggered this refactor in the
first place.
The dag package did not previously provide a topological walk of a given
graph. While the existing combination of a transitive reduction with a
depth-first walk appeared to accomplish this, depth-first is only
equivalent with a simple tree. If there are multiple paths to a node, a
depth-first approach will skip dependencies from alternate paths.
* refactor: Use tfaddr for provider address parsing
* refactor: Use tfaddr for module address parsing
* deps: introduce hashicorp/terraform-registry-address
We introduced the addrs.UniqueKey and addrs.UniqueKeyer mechanics as part
of implementing the ValidateMoves and ApplyMoves functions, as a way to
better encapsulate the solution to the problem that lots of our address
types aren't comparable and so cannot be used directly as map keys.
However, exposing addrs.UniqueKey handling directly in the logic adds
various noise to the algorithms and, in particular, obscures the fact that
MoveResults.Changes and MoveResult.Blocked both have different map key
types.
Here then we'll use the new addrs.Map helper type, which encapsulates the
idea of a map from an addrs.UniqueKeyer type to an arbitrary value type,
using the unique keys as the map keys internally. This does unfortunately
mean that we lose the conventional Go map access syntax and have to use
a method-based API instead, but I (subjectively) think that's an okay
compromise in return for avoiding the need to keep track inline of which
addrs.UniqueKey values correspond with which real addresses.
This is intended as an entirely-mechanical change, with equivalent
behavior to what it replaced. If anything here is doing something
materially different than what it replaced then that's a mistake.
Terraform uses "implied" move statements to represent the situation where
it automatically handles a switch from count to no-count on a resource.
Because that situation requires targeting only a specific resource
instance inside a specific module instance, implied move statements are
always presented as if they had been declared in the root module and then
traversed through the exact module instance path to reach the target
resource.
However, that means they can potentially cross a module package boundary,
if the changed resource belongs to an external module. Normally we
prohibit that to avoid the root module depending on implementation details
of the called module, but Terraform generates these implied statements
based only on information in the called module and so there's no need to
apply that same restriction to implied move statements, which will always
have source and destination addresses belonging to the same module
instance.
This change therefore fixes a misbehavior where Terraform would reject
an attempt to switch from no-count to count in a called module, where
previously the author of the calling configuration had no recourse to fix
it because the change has actually happened upstream.
Create a separate `validateMoveStatementGraph` function so that
`ValidateMoves` and `ApplyMoves` both check the same conditions. Since
we're not using the builtin `graph.Validate` method, because we may have
multiple roots and want better cycle diagnostics, we need to add checks
for self references too. While multiple roots are an error enforced by
`Validate` for the concurrent walk, they are OK when using
`TransitiveReduction` and `ReverseDepthFirstWalk`, so we can skip that
check.
Apply moves must first use `TransitiveReduction` to reduce the graph,
otherwise nodes may be skipped if they are passed over by a transitive
edge.
Changing only the index on a nested module will cause all nested moves
to create cycles, since their full addresses will match both the From
and To addresses. When building the dependency graph, check if the
parent is only changing the index of the containing module, and prevent
the backwards edge for the move.
When applying module `moved` statements by iterating through modules in
state, we previously required an exact match from the `moved`
statement's `from` field and the module address. This permitted moving
resources directly inside a module, but did not recur into module calls
within those moved modules.
This commit moves that exact match requirement so that it only applies
to `moved` statements targeting resources. In turn this allows nested
modules to be moved.
Earlier work to make "terraform init" interruptible made the getproviders
package context-aware in order to allow provider installation to be cancelled.
Here we make a similar change for module installation, which is now also
cancellable with SIGINT. This involves plumbing context through initwd and
getmodules. Functions which can make network requests now include a context
parameter whose cancellation cancels those requests.
Since the module installation code is shared, "terraform get" is now
also interruptible during module installation.