I recently - again - had to import resources to Terraform (0.11.14) from AWS that were outside of the default AWS region and were managed in a nested (non-root) module. The root module contained the provider configuration, including multiple aliases to allow creation of resources in different regions, as well as the nested module call, here in a very simple version:
provider "aws" { region = "us-west-2" } provider "aws" { region = "us-east-1" alias = "us-east-1" } provider "aws" { region = "us-west-2" alias = "us-west-2" } module "cloud" { param = value }
The goal was to import some aws_ses_email_identity resources into the "cloud" module. So, originally the cloud module had this:
resource "aws_ses_email_identity" "info_example_org" { email = "[email protected]" provider = "aws.us-west-2" }
This look perfectly ok, as the said email identity was in us-west-2. But what does "terraform import" do? Fail miserably:
$ terraform import module.cloud.aws_ses_email_identity.info_example_org [email protected] module.cloud.aws_ses_email_identity.info_example_org: Importing from ID "[email protected]"… module.cloud.aws_ses_email_identity.info_example_org: Import complete! Imported aws_ses_email_identity (ID: [email protected]) module.cloud.aws_ses_email_identity.info_example_org: Refreshing state… (ID: [email protected]) Error: module.cloud.aws_ses_email_identity.info_example_org (import id: [email protected]): 1 error occurred: * import module.cloud.aws_ses_email_identity.info_example_org result: [email protected]: aws_ses_email_identity.info_example.org: RequestError: send request failed caused by: Post https://email.us-west-1.amazonaws.com/: dial tcp: lookup email.us-west-1.amazonaws.com on 192.168.248.1:53: no such host
The "caused by" line shows that Terraform is reaching out to us-west-1, not us-west-2, when refreshing the state. This is a known problem and the workaround suggested by "apparentlysmart" is rather horrible, quoted in full below:
...I would probably try to work around it like this:
- Import the resource into the root module, using a provider that has the intended region statically configured.
- Use
terraform state mv
to move the state for the imported resource over into the target module. - Move the configuration block into the target module too.
- Run
terraform plan
to make sure things have settled.
Now this workaround actually does work in the above case, but is really horrible. So basically you hardcode the default provider in the root module to the region your to-be-imported resource resides in, and move the resource in there and remove the custom provider from the resource:
provider "aws" { region = "us-west-2" } --- snip --- resource "aws_ses_email_identity" "info_example_org" { email = "[email protected]" }
Now you can import the resource into the root module:
$ terraform import aws_ses_email_identity.info_example_org [email protected]
Then you change the default provider back to what it was:
provider "aws" { region = "us-west-1" }
Then you move the imported resource to the nested module. Make sure that in the nested module the resource does have the custom provider configuration:
resource "aws_ses_email_identity" "info_example_org" {
email = "[email protected]"
provider = "aws.us-west-2"
}
Then, finally, move the resource in the state file:
$ terraform state mv aws_ses_email_identity.info_example_org module.cloud.aws_ses_email_identity.info_example_org Moved aws_ses_email_identity.info_example_org to module.cloud.aws_ses_email_identity.info_example_org
Finally check the "terraform plan" looks sane:
$ terraform plan --- snip --- Plan: 0 to add, 0 to change, 0 to destroy. --- snip ---
Now pray that you do not have to go through this process often, or it will drive you crazy.