Resource Read method with query parameters

Is it possible to dynamically pass query parameters in a Terraform resource’s Read method?

We operate an API that we’ve built a Terraform provider for. We recently introduced a v2 for an API, which essentially has v2 versions of all v1 resources. The v2 API’s READ method offers migration support in the form of `migrate` parameter, such that when it’s set to true, it will fetch the v1 resource, map it to its v2 representation and return the mapped rep.

I’d like to expose this functionality in our Terraform provider. The workflow I have in mind is: a a practitioner adds an `import` block and runs `terraform plan -generate-config-out=“generated_resources.tf”`. When doing the import, the provider would then pass the `migrate=true` query parameter to the v2 API, and unmarshal the mapped v2 response to the v2 resource model, and return the v2 resource’s Terraform configuration.

One idea would be to add an identity block to the v2 resources consisting of the resource’s id and its version (as per the API). Then a v1 API “resource” could be imported into a v2 Terraform resource by an identity block consisting of the v1 resource’s id and its v1 version. Does that seem plausible?

Hi @csar398,

If you are asking about a situation where your provider has a different resource type for “v2” than it does for “v1” then you might be able to use the State move functionality to get a better user experience for this.

Someone who was previously using your “v1” resource type can include a declaration like this:

moved {
  from = example_v1.a
  to   = example_v2.a
}

…in which case if there’s already an object for example_v1.a tracked in the prior state, before calling “read” Terraform will first check if the provider knows how to translate a example_v1 object to the example_v2 schema, and then the logic in your provider could implement that by using the “migrate” feature you mentioned. If successful then Terraform will save the result as if it were the prior state for example_v2.a and then proceed with the normal read and planning calls.


Because this is “moving” rather than “importing” this does admittedly mean that there will be no automatic migration of the original source code: at the same time as adding the moved block, the author would also need to change their resource "example_v1" "a" block into a resource "example_v2" "a" block before running terraform plan or terraform apply, so that Terraform can understand that the intention is to migrate the existing object to that new configuration block.

If you think that the work to change an example_v1 config into an example_v2 config is too complex to be done manually, you could potentially offer your own tool to do that outside of the main Terraform workflow, since that’s usually where development tasks like editing code happen. But there isn’t any support for doing that automatically as part of the terraform plan command today.

Thanks for the great insight @apparentlymart.

But [`terraform plan -generate-config-out-path`]( terraform plan command reference | Terraform | HashiCorp Developer ) does support that (experimentally), doesn’t it?

I briefly considered implementing `ResourceWithMoveState` but discarded the option since I didn’t want to implement the v1 → v2 mapping in the provider or to dispatch it to an API call from the provider (read with query parameter migrate); I prefer to issue API calls only from within resources’ CRUD methods and keep them out of other provider lifecycle processes.

If I can verify there would be no side effects by calling the API from `MoveState`, I may implement it additionally (i haven’t worked with that yet, so I can’t tell). So a user could first just run `terraform plan -generate-config-out-path` to get the migrated resource’s config stub, and then replace the `import` block with a `moved` block targetting the generated (and possibly supplemented) config stub.