Skip to content

Commit

Permalink
Merge pull request #19311 from DrFaust92/r/vpn_connection_modify
Browse files Browse the repository at this point in the history
r/vpn_connection - modify from/to vgw/tgw
  • Loading branch information
ewbankkit authored Jan 11, 2022
2 parents 46486ce + b0648aa commit d30ffe1
Show file tree
Hide file tree
Showing 12 changed files with 2,223 additions and 1,579 deletions.
11 changes: 11 additions & 0 deletions .changelog/19311.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:enhancement
resource/aws_vpn_connection: `customer_gateway_id`, `transit_gateway_id` and `vpn_gateway_id` can be updated without recreating the resource
```

```release-note:enhancement
resource/aws_vpn_connection: `tunnel1_preshared_key` and `tunnel2_preshared_key` can be updated without recreating the resource
```

```release-note:enhancement
resource/aws_vpn_connection: Add `vgw_telemetry.certificate_arn` attribute
```
14 changes: 14 additions & 0 deletions internal/service/ec2/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const (
VpcEndpointStateRejected = "rejected"
)

const (
VpnStateModifying = "modifying"
)

// See https://docs.aws.amazon.com/vm-import/latest/userguide/vmimport-image-import.html#check-import-task-status
const (
EBSSnapshotImportStateActive = "active"
Expand Down Expand Up @@ -53,3 +57,13 @@ const (
CustomerGatewayStateDeleting = "deleting"
CustomerGatewayStatePending = "pending"
)

const (
VpnConnectionTypeIpsec1 = "ipsec.1"
)

func VpnConnectionType_Values() []string {
return []string{
VpnConnectionTypeIpsec1,
}
}
90 changes: 46 additions & 44 deletions internal/service/ec2/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,52 @@ import (
)

const (
ErrCodeClientInvalidHostIDNotFound = "Client.InvalidHostID.NotFound"
ErrCodeClientVpnAssociationIdNotFound = "InvalidClientVpnAssociationId.NotFound"
ErrCodeClientVpnAuthorizationRuleNotFound = "InvalidClientVpnEndpointAuthorizationRuleNotFound"
ErrCodeClientVpnEndpointIdNotFound = "InvalidClientVpnEndpointId.NotFound"
ErrCodeClientVpnRouteNotFound = "InvalidClientVpnRouteNotFound"
ErrCodeDependencyViolation = "DependencyViolation"
ErrCodeGatewayNotAttached = "Gateway.NotAttached"
ErrCodeIncorrectState = "IncorrectState"
ErrCodeInvalidAssociationIDNotFound = "InvalidAssociationID.NotFound"
ErrCodeInvalidAttachmentIDNotFound = "InvalidAttachmentID.NotFound"
ErrCodeInvalidCarrierGatewayIDNotFound = "InvalidCarrierGatewayID.NotFound"
ErrCodeInvalidCustomerGatewayIDNotFound = "InvalidCustomerGatewayID.NotFound"
ErrCodeInvalidFlowLogIdNotFound = "InvalidFlowLogId.NotFound"
ErrCodeInvalidGroupNotFound = "InvalidGroup.NotFound"
ErrCodeInvalidHostIDNotFound = "InvalidHostID.NotFound"
ErrCodeInvalidInstanceIDNotFound = "InvalidInstanceID.NotFound"
ErrCodeInvalidInternetGatewayIDNotFound = "InvalidInternetGatewayID.NotFound"
ErrCodeInvalidKeyPairNotFound = "InvalidKeyPair.NotFound"
ErrCodeInvalidNetworkInterfaceIDNotFound = "InvalidNetworkInterfaceID.NotFound"
ErrCodeInvalidParameter = "InvalidParameter"
ErrCodeInvalidParameterException = "InvalidParameterException"
ErrCodeInvalidParameterValue = "InvalidParameterValue"
ErrCodeInvalidPermissionDuplicate = "InvalidPermission.Duplicate"
ErrCodeInvalidPermissionMalformed = "InvalidPermission.Malformed"
ErrCodeInvalidPermissionNotFound = "InvalidPermission.NotFound"
ErrCodeInvalidPlacementGroupUnknown = "InvalidPlacementGroup.Unknown"
ErrCodeInvalidPrefixListIDNotFound = "InvalidPrefixListID.NotFound"
ErrCodeInvalidRouteNotFound = "InvalidRoute.NotFound"
ErrCodeInvalidRouteTableIDNotFound = "InvalidRouteTableID.NotFound"
ErrCodeInvalidRouteTableIdNotFound = "InvalidRouteTableId.NotFound"
ErrCodeInvalidSecurityGroupIDNotFound = "InvalidSecurityGroupID.NotFound"
ErrCodeInvalidSpotInstanceRequestIDNotFound = "InvalidSpotInstanceRequestID.NotFound"
ErrCodeInvalidSubnetCidrReservationIDNotFound = "InvalidSubnetCidrReservationID.NotFound"
ErrCodeInvalidSubnetIDNotFound = "InvalidSubnetID.NotFound"
ErrCodeInvalidSubnetIdNotFound = "InvalidSubnetId.NotFound"
ErrCodeInvalidTransitGatewayIDNotFound = "InvalidTransitGatewayID.NotFound"
ErrCodeInvalidVpcEndpointIdNotFound = "InvalidVpcEndpointId.NotFound"
ErrCodeInvalidVpcEndpointNotFound = "InvalidVpcEndpoint.NotFound"
ErrCodeInvalidVpcEndpointServiceIdNotFound = "InvalidVpcEndpointServiceId.NotFound"
ErrCodeInvalidVpcIDNotFound = "InvalidVpcID.NotFound"
ErrCodeInvalidVpcPeeringConnectionIDNotFound = "InvalidVpcPeeringConnectionID.NotFound"
ErrCodeInvalidVpnGatewayAttachmentNotFound = "InvalidVpnGatewayAttachment.NotFound"
ErrCodeInvalidVpnGatewayIDNotFound = "InvalidVpnGatewayID.NotFound"
ErrCodeInvalidSnapshotNotFound = "InvalidSnapshot.NotFound"
ErrCodeClientInvalidHostIDNotFound = "Client.InvalidHostID.NotFound"
ErrCodeClientVpnAssociationIdNotFound = "InvalidClientVpnAssociationId.NotFound"
ErrCodeClientVpnAuthorizationRuleNotFound = "InvalidClientVpnEndpointAuthorizationRuleNotFound"
ErrCodeClientVpnEndpointIdNotFound = "InvalidClientVpnEndpointId.NotFound"
ErrCodeClientVpnRouteNotFound = "InvalidClientVpnRouteNotFound"
ErrCodeDependencyViolation = "DependencyViolation"
ErrCodeGatewayNotAttached = "Gateway.NotAttached"
ErrCodeIncorrectState = "IncorrectState"
ErrCodeInvalidAssociationIDNotFound = "InvalidAssociationID.NotFound"
ErrCodeInvalidAttachmentIDNotFound = "InvalidAttachmentID.NotFound"
ErrCodeInvalidCarrierGatewayIDNotFound = "InvalidCarrierGatewayID.NotFound"
ErrCodeInvalidCustomerGatewayIDNotFound = "InvalidCustomerGatewayID.NotFound"
ErrCodeInvalidFlowLogIdNotFound = "InvalidFlowLogId.NotFound"
ErrCodeInvalidGroupNotFound = "InvalidGroup.NotFound"
ErrCodeInvalidHostIDNotFound = "InvalidHostID.NotFound"
ErrCodeInvalidInstanceIDNotFound = "InvalidInstanceID.NotFound"
ErrCodeInvalidInternetGatewayIDNotFound = "InvalidInternetGatewayID.NotFound"
ErrCodeInvalidKeyPairNotFound = "InvalidKeyPair.NotFound"
ErrCodeInvalidNetworkInterfaceIDNotFound = "InvalidNetworkInterfaceID.NotFound"
ErrCodeInvalidParameter = "InvalidParameter"
ErrCodeInvalidParameterException = "InvalidParameterException"
ErrCodeInvalidParameterValue = "InvalidParameterValue"
ErrCodeInvalidPermissionDuplicate = "InvalidPermission.Duplicate"
ErrCodeInvalidPermissionMalformed = "InvalidPermission.Malformed"
ErrCodeInvalidPermissionNotFound = "InvalidPermission.NotFound"
ErrCodeInvalidPlacementGroupUnknown = "InvalidPlacementGroup.Unknown"
ErrCodeInvalidPrefixListIDNotFound = "InvalidPrefixListID.NotFound"
ErrCodeInvalidRouteNotFound = "InvalidRoute.NotFound"
ErrCodeInvalidRouteTableIDNotFound = "InvalidRouteTableID.NotFound"
ErrCodeInvalidRouteTableIdNotFound = "InvalidRouteTableId.NotFound"
ErrCodeInvalidSecurityGroupIDNotFound = "InvalidSecurityGroupID.NotFound"
ErrCodeInvalidSnapshotNotFound = "InvalidSnapshot.NotFound"
ErrCodeInvalidSpotInstanceRequestIDNotFound = "InvalidSpotInstanceRequestID.NotFound"
ErrCodeInvalidSubnetCidrReservationIDNotFound = "InvalidSubnetCidrReservationID.NotFound"
ErrCodeInvalidSubnetIDNotFound = "InvalidSubnetID.NotFound"
ErrCodeInvalidSubnetIdNotFound = "InvalidSubnetId.NotFound"
ErrCodeInvalidTransitGatewayAttachmentIDNotFound = "InvalidTransitGatewayAttachmentID.NotFound"
ErrCodeInvalidTransitGatewayIDNotFound = "InvalidTransitGatewayID.NotFound"
ErrCodeInvalidVpcEndpointIdNotFound = "InvalidVpcEndpointId.NotFound"
ErrCodeInvalidVpcEndpointNotFound = "InvalidVpcEndpoint.NotFound"
ErrCodeInvalidVpcEndpointServiceIdNotFound = "InvalidVpcEndpointServiceId.NotFound"
ErrCodeInvalidVpcIDNotFound = "InvalidVpcID.NotFound"
ErrCodeInvalidVpcPeeringConnectionIDNotFound = "InvalidVpcPeeringConnectionID.NotFound"
ErrCodeInvalidVpnConnectionIDNotFound = "InvalidVpnConnectionID.NotFound"
ErrCodeInvalidVpnGatewayAttachmentNotFound = "InvalidVpnGatewayAttachment.NotFound"
ErrCodeInvalidVpnGatewayIDNotFound = "InvalidVpnGatewayID.NotFound"
)

func UnsuccessfulItemError(apiObject *ec2.UnsuccessfulItemError) error {
Expand Down
148 changes: 148 additions & 0 deletions internal/service/ec2/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,154 @@ func FindCustomerGateway(conn *ec2.EC2, input *ec2.DescribeCustomerGatewaysInput
return output.CustomerGateways[0], nil
}

func FindVPNConnectionByID(conn *ec2.EC2, id string) (*ec2.VpnConnection, error) {
input := &ec2.DescribeVpnConnectionsInput{
VpnConnectionIds: aws.StringSlice([]string{id}),
}

output, err := FindVPNConnection(conn, input)

if err != nil {
return nil, err
}

if state := aws.StringValue(output.State); state == ec2.VpnStateDeleted {
return nil, &resource.NotFoundError{
Message: state,
LastRequest: input,
}
}

// Eventual consistency check.
if aws.StringValue(output.VpnConnectionId) != id {
return nil, &resource.NotFoundError{
LastRequest: input,
}
}

return output, nil
}

func FindVPNConnection(conn *ec2.EC2, input *ec2.DescribeVpnConnectionsInput) (*ec2.VpnConnection, error) {
output, err := conn.DescribeVpnConnections(input)

if tfawserr.ErrCodeEquals(err, ErrCodeInvalidVpnConnectionIDNotFound) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || len(output.VpnConnections) == 0 || output.VpnConnections[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

if count := len(output.VpnConnections); count > 1 {
return nil, tfresource.NewTooManyResultsError(count, input)
}

return output.VpnConnections[0], nil
}

func FindVPNConnectionRouteByVPNConnectionIDAndCIDR(conn *ec2.EC2, vpnConnectionID, cidrBlock string) (*ec2.VpnStaticRoute, error) {
input := &ec2.DescribeVpnConnectionsInput{
Filters: BuildAttributeFilterList(map[string]string{
"route.destination-cidr-block": cidrBlock,
"vpn-connection-id": vpnConnectionID,
}),
}

output, err := FindVPNConnection(conn, input)

if err != nil {
return nil, err
}

for _, v := range output.Routes {
if aws.StringValue(v.DestinationCidrBlock) == cidrBlock && aws.StringValue(v.State) != ec2.VpnStateDeleted {
return v, nil
}
}

return nil, &resource.NotFoundError{
LastError: fmt.Errorf("EC2 VPN Connection (%s) Route (%s) not found", vpnConnectionID, cidrBlock),
}
}

func FindTransitGatewayAttachment(conn *ec2.EC2, input *ec2.DescribeTransitGatewayAttachmentsInput) (*ec2.TransitGatewayAttachment, error) {
output, err := FindTransitGatewayAttachments(conn, input)

if err != nil {
return nil, err
}

if len(output) == 0 || output[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

if count := len(output); count > 1 {
return nil, tfresource.NewTooManyResultsError(count, input)
}

return output[0], nil
}

func FindTransitGatewayAttachments(conn *ec2.EC2, input *ec2.DescribeTransitGatewayAttachmentsInput) ([]*ec2.TransitGatewayAttachment, error) {
var output []*ec2.TransitGatewayAttachment

err := conn.DescribeTransitGatewayAttachmentsPages(input, func(page *ec2.DescribeTransitGatewayAttachmentsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, v := range page.TransitGatewayAttachments {
if v != nil {
output = append(output, v)
}
}

return !lastPage
})

if tfawserr.ErrCodeEquals(err, ErrCodeInvalidTransitGatewayAttachmentIDNotFound) {
return nil, &resource.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

return output, nil
}

func FindTransitGatewayAttachmentByID(conn *ec2.EC2, id string) (*ec2.TransitGatewayAttachment, error) {
input := &ec2.DescribeTransitGatewayAttachmentsInput{
TransitGatewayAttachmentIds: aws.StringSlice([]string{id}),
}

output, err := FindTransitGatewayAttachment(conn, input)

if err != nil {
return nil, err
}

// Eventual consistency check.
if aws.StringValue(output.TransitGatewayAttachmentId) != id {
return nil, &resource.NotFoundError{
LastRequest: input,
}
}

return output, nil
}

func FindFlowLogByID(conn *ec2.EC2, id string) (*ec2.FlowLog, error) {
input := &ec2.DescribeFlowLogsInput{
FlowLogIds: aws.StringSlice([]string{id}),
Expand Down
32 changes: 32 additions & 0 deletions internal/service/ec2/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,38 @@ func StatusCustomerGatewayState(conn *ec2.EC2, id string) resource.StateRefreshF
}
}

func StatusVPNConnectionState(conn *ec2.EC2, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindVPNConnectionByID(conn, id)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.State), nil
}
}

func StatusVPNConnectionRouteState(conn *ec2.EC2, vpnConnectionID, cidrBlock string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindVPNConnectionRouteByVPNConnectionIDAndCIDR(conn, vpnConnectionID, cidrBlock)

if tfresource.NotFound(err) {
return nil, "", nil
}

if err != nil {
return nil, "", err
}

return output, aws.StringValue(output.State), nil
}
}

func StatusHostState(conn *ec2.EC2, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindHostByID(conn, id)
Expand Down
33 changes: 12 additions & 21 deletions internal/service/ec2/sweep.go
Original file line number Diff line number Diff line change
Expand Up @@ -2044,8 +2044,8 @@ func sweepVPNConnections(region string) error {
}
conn := client.(*conns.AWSClient).EC2Conn
input := &ec2.DescribeVpnConnectionsInput{}
sweepResources := make([]*sweep.SweepResource, 0)

// DescribeVpnConnections does not currently have any form of pagination
output, err := conn.DescribeVpnConnections(input)

if sweep.SkipSweepError(err) {
Expand All @@ -2054,34 +2054,25 @@ func sweepVPNConnections(region string) error {
}

if err != nil {
return fmt.Errorf("error retrieving EC2 VPN Connections: %s", err)
return fmt.Errorf("error listing EC2 VPN Connections (%s): %w", region, err)
}

for _, vpnConnection := range output.VpnConnections {
if aws.StringValue(vpnConnection.State) == ec2.VpnStateDeleted {
for _, v := range output.VpnConnections {
if aws.StringValue(v.State) == ec2.VpnStateDeleted {
continue
}

id := aws.StringValue(vpnConnection.VpnConnectionId)
input := &ec2.DeleteVpnConnectionInput{
VpnConnectionId: vpnConnection.VpnConnectionId,
}

log.Printf("[INFO] Deleting EC2 VPN Connection: %s", id)

_, err := conn.DeleteVpnConnection(input)
r := ResourceVPNConnection()
d := r.Data(nil)
d.SetId(aws.StringValue(v.VpnConnectionId))

if tfawserr.ErrMessageContains(err, "InvalidVpnConnectionID.NotFound", "") {
continue
}
sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client))
}

if err != nil {
return fmt.Errorf("error deleting EC2 VPN Connection (%s): %s", id, err)
}
err = sweep.SweepOrchestrator(sweepResources)

if err := WaitForVPNConnectionDeletion(conn, id); err != nil {
return fmt.Errorf("error waiting for VPN connection (%s) to delete: %s", id, err)
}
if err != nil {
return fmt.Errorf("error sweeping EC2 VPN Connections (%s): %w", region, err)
}

return nil
Expand Down
Loading

0 comments on commit d30ffe1

Please sign in to comment.