0

I have AWS clientVPN which was created manually from AWS console and it has around 20 plus route table entry. Now, I want to terraform this so we can add any new route using terraform.

I have imported the ClientVPN information using terraform import. To import all the existing routes, I can import one route at a time also for each route Import I need to add resource entry in main.tf as shown below:

Command used to import the route table entry:
$ terraform import aws_ec2_client_vpn_route.example cvpn-endpoint-0e3e121d2,subnet-08acf2,<CIDR>
This command updates the .tfstate file and when I run terraform plan it gives me an error because I need to add resource section for this in main.tf file. 

resource "aws_ec2_client_vpn_route" "example" {
  client_vpn_endpoint_id = var.client_vpn_endpoint_id
  destination_cidr_block = "CIDR"
  target_vpc_subnet_id   = var.target_vpc_subnet_id
}

resource "aws_ec2_client_vpn_route" "example1" {
  client_vpn_endpoint_id = var.client_vpn_endpoint_id
  destination_cidr_block = "CIDR"
  target_vpc_subnet_id   = var.target_vpc_subnet_id
}

Each time, I import the route, I need to add resource in main.tf. If I have 20 route table entry then I have to write 20 resource entry in main.tf file?

I just want to use one resource entry in main.tf, how is it possible?

After import, when I ran the terraform plan, check the output:

% terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_ec2_client_vpn_route.example: Refreshing state... [id=cvpn-endpoint,subnet-02231,0.0.0.0/16]
aws_ec2_client_vpn_endpoint.example: Refreshing state... [id=cvpn-endpoint]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
  - destroy

Terraform will perform the following actions:

  # aws_ec2_client_vpn_route.example will be destroyed
  - resource "aws_ec2_client_vpn_route" "example" {
      - client_vpn_endpoint_id = "cvpn-endpoint" -> null
      - description            = "Default Route" -> null
      - destination_cidr_block = "0.0.0.0/16" -> null
      - id                     = "cvpn-endpoint,subnet-02231308,0.0.0.0/16" -> null
      - origin                 = "associate" -> null
      - target_vpc_subnet_id   = "subnet-022313" -> null
      - type                   = "Nat" -> null
    }

  # aws_ec2_client_vpn_route.example["Default Route"] will be created
  + resource "aws_ec2_client_vpn_route" "example" {
      + client_vpn_endpoint_id = "cvpn-endpoint"
      + description            = "Default Route"
      + destination_cidr_block = "0.0.0.0/16"
      + id                     = (known after apply)
      + origin                 = (known after apply)
      + target_vpc_subnet_id   = "subnet-022313"
      + type                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Resource name are not matching thats why it is destroying and creating again. But, when I do terraform apply, it fails because it first create the resource and it fails because of same CIDR.

  • 1
    You could write it as a `for_each` on the resource and then import as the appropriate index. If you're new to Terraform then this might be a bit confusing though. – ydaetskcoR Sep 14 '21 at 09:02
  • Yes, I'm new to terraform. Could you please help me with this or any link or doc you can point me to. – Techhack New Sep 14 '21 at 09:04
  • 1
    https://www.terraform.io/docs/language/meta-arguments/for_each.html and https://www.terraform.io/docs/cli/commands/import.html#example-import-into-resource-configured-with-for_each – ydaetskcoR Sep 14 '21 at 09:05
  • I managed to use for_each but the problem is due to name mismatch(.tfstate file and resource name is not matching) terraform is creating new resources and destroying the imported rule. Any idea, how to fix this? @ydaetskcoR – Techhack New Sep 14 '21 at 09:51
  • 1
    Can you edit your question to show exactly what you've tried and the resulting errors or plan output when you run a command (also show the commands you run) please? – ydaetskcoR Sep 14 '21 at 10:09
  • @ydaetskcoR added terraform plan output – Techhack New Sep 14 '21 at 12:16
  • 1
    That looks like you've previously applied/imported a resource called `aws_ec2_client_vpn_route.example` and now removed the configuration for it so Terraform wants to remove it. You can instead remove it from state with `terraform state rm aws_ec2_client_vpn_route.example` and then run the plan again. It looks like you haven't properly imported the `aws_ec2_client_vpn_route.example[\"Default Route\"]` resource either so need to do that as per the second link in my above comment. – ydaetskcoR Sep 14 '21 at 12:33
  • 1
    At this point though I think you're maybe a little in over your head. I'd probably stop for a little bit and run through some simpler things or the courses on https://learn.hashicorp.com/ rather than trying to do more advanced things with what looks to be production resources. – ydaetskcoR Sep 14 '21 at 12:34

1 Answers1

2

You can use the for_each method that Terraform provides, which basically loops and creates the number of resources you have in the variable resource list.

variable "cidr_blocks" {
  description = ""
  default     = {
    "10.0.0.1/16" = 1
    "10.0.0.2/16" = 2
    "10.0.0.3/16" = 3
  }
}

resource "aws_ec2_client_vpn_route" "example" {
  for_each = var.cidr_blocks

  client_vpn_endpoint_id = var.client_vpn_endpoint_id
  destination_cidr_block = each.key
  target_vpc_subnet_id   = var.target_vpc_subnet_id
}

In this example you will create 3 aws_ec2_client_vpn_route resources.

bembas
  • 762
  • 8
  • 20