-
Notifications
You must be signed in to change notification settings - Fork 9.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
resource/aws_route: Support route import #5687
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @YakDriver 👋 Thanks for splitting this out!
I think we should take a look at creating an Importer.State
function that simplifies this process (example below) and also avoid having a second format for the resource ID. While the resource ID change is likely an inconsequential change since it would be non-trivial to use downstream in its current form with HashString
, we do not really have a precedent for changing resource IDs. For now, I think we should just avoid changing it in case we ever do need some process or reason to change it in the future so we do not need to handle two possible resource ID formats in existing Terraform states (which is also not obvious without updating the resource SchemaVersion
).
Please reach out with any questions or if you do not have time to implement this feedback, thanks!
aws/resource_aws_route.go
Outdated
@@ -28,6 +27,9 @@ func resourceAwsRoute() *schema.Resource { | |||
Update: resourceAwsRouteUpdate, | |||
Delete: resourceAwsRouteDelete, | |||
Exists: resourceAwsRouteExists, | |||
Importer: &schema.ResourceImporter{ | |||
State: resourceAwsRouteImportState, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To support resource import when the Terraform resource ID is not usable for the resource Read
function, it only requires setting up the necessary Terraform state attributes so the resource Read
function can work. As written, a lot of the changes in this pull request are extraneous unless we are planning on using the resource ID exclusively for the read function. Given this resource code looks very outdated for current best practices and that this pull request creates a second possibility for the format of the resource ID in Terraform states out in the wild, I would recommend only doing the bare minimum here.
To that last point, we should be able support import without changing other functionality in the resource via something like:
Importer: &schema.ResourceImporter{
State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
idParts := strings.Split(d.Id(), "_")
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
return nil, fmt.Errorf("Unexpected format of ID (%q), expected ROUTETABLEID_DESTINATION", d.Id())
}
routeTableID := idParts[0]
destination := idParts[1]
d.Set("route_table_id", routeTableID)
if strings.Contains(destination, ":") {
d.Set("destination_ipv6_cidr_block", destination)
} else {
d.Set("destination_cidr_block", destination)
}
d.SetId(fmt.Sprintf("r-%s%d", routeTableID, hashcode.String(destination)))
return []*schema.ResourceData{d}, nil
},
},
This supports resource import without the leading r-
as well.
This can be acceptance tested via:
// Inside import TestStep's
ImportStateIdFunc: testAccAWSRouteImportStateIdFunc(resourceName),
// ...
func testAccAWSRouteImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return "", fmt.Errorf("Not found: %s", resourceName)
}
if v, ok := rs.Primary.Attributes["destination_ipv6_cidr_block"]; ok && v != "" {
return fmt.Sprintf("%s_%s", rs.Primary.Attributes["route_table_id"], v), nil
}
return fmt.Sprintf("%s_%s", rs.Primary.Attributes["route_table_id"], rs.Primary.Attributes["destination_cidr_block"]), nil
}
See also pull requests like #5567
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! I was referencing the aws_route53_record
so that's where some of the outdated stuff comes from. This way is cleaner.
aws/import_aws_route_test.go
Outdated
"github.com/hashicorp/terraform/helper/resource" | ||
) | ||
|
||
func TestAccAWSRoute_importBasic(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are not creating additional configurations for testing import, the import TestStep
can simply be added to existing tests. The same applies to the other new tests below. e.g.
func TestAccAWSRoute_basic(t *testing.T) {
// ... existing test function ...
resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRouteDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSRouteBasicConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRouteExists("aws_route.bar", &route),
testCheck,
),
},
{
ResourceName: "aws_route.bar",
ImportState: true,
ImportStateIdFunc: testAccAWSRouteImportStateIdFunc("aws_route.bar"),
ImportStateVerify: true,
},
},
})
}
aws/resource_aws_route.go
Outdated
@@ -54,19 +57,16 @@ func resourceAwsRoute() *schema.Resource { | |||
"gateway_id": { | |||
Type: schema.TypeString, | |||
Optional: true, | |||
Computed: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this change intentional? If so, why? Same with the other Computed: true
removals. They seem unrelated to supporting resource import.
aws/resource_aws_route.go
Outdated
@@ -77,13 +77,13 @@ func resourceAwsRoute() *schema.Resource { | |||
|
|||
"instance_owner_id": { | |||
Type: schema.TypeString, | |||
Optional: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This attribute does not appear to be configurable in the resource Create
or Update
functions. Why was Optional: true
added here? It also seems unrelated to supporting resource import.
aws/resource_aws_route.go
Outdated
@@ -112,6 +112,12 @@ func resourceAwsRoute() *schema.Resource { | |||
|
|||
func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error { | |||
conn := meta.(*AWSClient).ec2conn | |||
|
|||
err := resourceAwsRouteCheckForImport(d) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During the Create
function, the ResourceData
will always be empty, so this is extraneous. This should be removed regardless of simplifying the import functionality.
aws/resource_aws_route.go
Outdated
resourceAwsRouteSetResourceData(d, route) | ||
return nil | ||
} | ||
|
||
func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
err := resourceAwsRouteCheckForImport(d) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Importer.State
and Create
functions should handle ID errors and setting the appropriate Terraform state required for read unless we switch to using schema.ImportStatePassthrough
for Importer.State
. The same applies to other usage in Update
/Delete
/Exists
.
website/docs/r/route.html.markdown
Outdated
|
||
## Import | ||
|
||
Individual routes can be imported using a pseudo ID defined as r-ROUTETABLEID_DESTINATION. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we simplify the using something like the example import function mentioned earlier, we can remove r-
from import. 👍
website/docs/r/route.html.markdown
Outdated
Individual routes can be imported using a pseudo ID defined as r-ROUTETABLEID_DESTINATION. | ||
|
||
For example, to import a route in a route table with ID rtb-656C65616E6F72 and an IPv4 CIDR destination of 10.42.0.0/16, | ||
the import ID would be as follows: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: We can remove the indirection of calling something the "import ID" and just show what we mean:
For example, to import a route in a route table with ID `rtb-656C65616E6F72` and an IPv4 CIDR destination of `10.42.0.0/16`:
```
$ terraform import aws_route.my_route rtb-656C65616E6F72_10.42.0.0/16
```
To import a route from route table `rtb-656C65616E6F72` with an IPv6 destination CIDR of `2620:0:2d0:200::8/125`:
```
$ terraform import aws_route.my_route rtb-656C65616E6F72_2620:0:2d0:200::8/125
```
706624f
to
ccaf208
Compare
@bflad I've implemented the changes. Let me know if you see anything else. |
New tests... $ make testacc TESTARGS='-run=TestAccAWSRoute_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./... -v -run=TestAccAWSRoute_ -timeout 120m
? github.com/terraform-providers/terraform-provider-aws [no test files]
=== RUN TestAccAWSRoute_basic
--- PASS: TestAccAWSRoute_basic (50.57s)
=== RUN TestAccAWSRoute_ipv6Support
--- PASS: TestAccAWSRoute_ipv6Support (41.06s)
=== RUN TestAccAWSRoute_ipv6ToInternetGateway
--- PASS: TestAccAWSRoute_ipv6ToInternetGateway (45.98s)
=== RUN TestAccAWSRoute_ipv6ToInstance
--- PASS: TestAccAWSRoute_ipv6ToInstance (139.54s)
=== RUN TestAccAWSRoute_ipv6ToNetworkInterface
--- PASS: TestAccAWSRoute_ipv6ToNetworkInterface (179.74s)
=== RUN TestAccAWSRoute_ipv6ToPeeringConnection
--- PASS: TestAccAWSRoute_ipv6ToPeeringConnection (41.01s)
=== RUN TestAccAWSRoute_changeRouteTable
--- PASS: TestAccAWSRoute_changeRouteTable (75.50s)
=== RUN TestAccAWSRoute_changeCidr
--- PASS: TestAccAWSRoute_changeCidr (80.10s)
=== RUN TestAccAWSRoute_noopdiff
--- PASS: TestAccAWSRoute_noopdiff (120.35s)
=== RUN TestAccAWSRoute_doesNotCrashWithVPCEndpoint
--- PASS: TestAccAWSRoute_doesNotCrashWithVPCEndpoint (55.98s)
PASS
ok github.com/terraform-providers/terraform-provider-aws/aws 829.873s |
ccaf208
to
5e8f990
Compare
Enable use of standard import mechanism to import aws_route resources. The enhancement was complicated by AWS not assigning route table routes (aws_route) an ID. However, a route can be uniquely identified with a route table ID and CIDR destination. Thus, creating a pseudo ID defined by r-ROUTETABLEID_CIDRDESTINATION allows routes to be identified and imported. Related hashicorp#5631, #704, hashicorp/terraform#13779
5e8f990
to
3404a0b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM -- thanks @YakDriver! 🚀
10 tests passed (all tests)
--- PASS: TestAccAWSRoute_ipv6ToPeeringConnection (19.75s)
--- PASS: TestAccAWSRoute_ipv6Support (21.28s)
--- PASS: TestAccAWSRoute_basic (30.94s)
--- PASS: TestAccAWSRoute_ipv6ToInternetGateway (31.97s)
--- PASS: TestAccAWSRoute_doesNotCrashWithVPCEndpoint (34.51s)
--- PASS: TestAccAWSRoute_changeRouteTable (42.86s)
--- PASS: TestAccAWSRoute_changeCidr (53.14s)
--- PASS: TestAccAWSRoute_ipv6ToInstance (100.42s)
--- PASS: TestAccAWSRoute_noopdiff (173.03s)
--- PASS: TestAccAWSRoute_ipv6ToNetworkInterface (175.56s)
This has been released in version 1.34.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. |
Import route tables using inline routes in the resource data. This is the same way resource data is structured when routes tables are read (and created) which enables imports to line up properly with existing resources. Previously, if you applied a state that included the import of a route table, all routes in the route table would be deleted. This bug occurred because the import function (resourceAwsRouteTableImportState()) would return a target state including both a route table resource and separate route resources for each route. The route table read function (resourceAwsRouteTableRead()) returns a state with a route table resource having inline routes. Despite being equivalent, since the states did not match, Terraform would delete all routes in the route table when applying the change plan. Fixes hashicorp#5631 Update functions names to comply with convention This commit is planned to occur after PR hashicorp#5687 which changes the names of these functions. In order to avoid merge conflicts at that time, this pre-emptively renames the functions.
Import route tables using inline routes in the resource data. This is the same way resource data is structured when routes tables are read (and created) which enables imports to line up properly with existing resources. Previously, if you applied a state that included the import of a route table, all routes in the route table would be deleted. This bug occurred because the import function (resourceAwsRouteTableImportState()) would return a target state including both a route table resource and separate route resources for each route. The route table read function (resourceAwsRouteTableRead()) returns a state with a route table resource having inline routes. Despite being equivalent, since the states did not match, Terraform would delete all routes in the route table when applying the change plan. Fixes hashicorp#5631 Update functions names to comply with convention This commit is planned to occur after PR hashicorp#5687 which changes the names of these functions. In order to avoid merge conflicts at that time, this pre-emptively renames the functions.
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks! |
Changes proposed in this pull request:
Output from acceptance testing: