Skip to content

Commit

Permalink
r/aws_route: Support changing network_interface_id
Browse files Browse the repository at this point in the history
The fix in hashicorp/terraform#7686 causes the
exact same bug in reverse (if you specify network_interface_id in
config, apply, and then change the network_interface_id, it will apply
the old instance_id, which is a no-op).

This checks which has changed from the instance state, allowing us to
change either network_interface_id or instance_id correctly.
  • Loading branch information
raylu-stripe committed Nov 17, 2017
1 parent 65dcda3 commit 10aaccc
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 11 deletions.
29 changes: 18 additions & 11 deletions aws/resource_aws_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ func prepareRouteUpdate(d *schema.ResourceData) (*ec2.ReplaceRouteInput, error)
"egress_only_gateway_id",
"gateway_id",
"nat_gateway_id",
"network_interface_id",
"instance_id",
"network_interface_id",
"vpc_peering_connection_id",
}

Expand All @@ -312,16 +312,23 @@ func prepareRouteUpdate(d *schema.ResourceData) (*ec2.ReplaceRouteInput, error)
}
}

switch setTarget {
//instance_id is a special case due to the fact that AWS will "discover" the network_interace_id
//when it creates the route and return that data. In the case of an update, we should ignore the
//existing network_interface_id
case "instance_id":
if numTargets > 2 || (numTargets == 2 && len(d.Get("network_interface_id").(string)) == 0) {
return nil, routeTargetValidationError
}
default:
if numTargets > 1 {
if numTargets > 1 {
if setTarget == "network_interface_id" && numTargets == 2 {
// instance_id and network_interface_id are both computed from each
// other. Specifying either in config will cause the other to be
// computed by resourceAwsRouteSetResourceData, so they will both show up
// as targets.
if len(d.Get("instance_id").(string)) == 0 {
return nil, routeTargetValidationError
}
// We check network_interface_id after instance_id in allowedTargets, so
// we will always prefer network_interface_id. If instance_id is the one
// that has changed from the instance state, we should update that
// instead.
if d.HasChange("instance_id") && !d.HasChange("network_interface_id") {
setTarget = "instance_id"
}
} else {
return nil, routeTargetValidationError
}
}
Expand Down
23 changes: 23 additions & 0 deletions aws/resource_aws_route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,29 @@ func TestAWSRoute_instanceIdChange(t *testing.T) {
}
}

func TestAWSRoute_networkInterfaceIdChange(t *testing.T) {
r := resourceAwsRoute()

state := map[string]string{
"instance_id": "i-1",
"network_interface_id": "eni-1",
}
raw := map[string]interface{}{
"network_interface_id": "eni-2",
}
d := schema.TestResourceDataStateRaw(t, r.Schema, state, raw)
replaceOpts, err := prepareRouteUpdate(d)
if err != nil {
t.Fatal(err)
}
if replaceOpts.InstanceId != nil {
t.Error("InstanceId changed", replaceOpts)
}
if replaceOpts.NetworkInterfaceId == nil || *replaceOpts.NetworkInterfaceId != "eni-2" {
t.Error("NetworkInterfaceId unchanged", replaceOpts)
}
}

func testAccCheckAWSRouteExists(n string, res *ec2.Route) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down

0 comments on commit 10aaccc

Please sign in to comment.