Skip to content

Commit

Permalink
merge changes from master for service/ec2: Add Resource & Data Source…
Browse files Browse the repository at this point in the history
… aws_ec2_transit_gateway_peering_attachment (hashicorp#11162)

Output from acceptance testing:

```
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachment_basic (279.30s)
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachment_differentAccount (274.76s)
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachment_disappears (298.80s)
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachment_Tags_sameAccount (341.73s)

--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_Filter_differentAccount (290.68s)
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_Filter_sameAccount (281.60s)
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_ID_differentAccount (291.70s)
--- PASS: TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_ID_sameAccount (308.69s)
```
  • Loading branch information
Omarimcblack committed May 1, 2020
1 parent 01be436 commit 4cee185
Show file tree
Hide file tree
Showing 15 changed files with 1,191 additions and 4 deletions.
105 changes: 105 additions & 0 deletions aws/data_source_aws_ec2_transit_gateway_peering_attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package aws

import (
"errors"
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func dataSourceAwsEc2TransitGatewayPeeringAttachment() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsEc2TransitGatewayPeeringAttachmentRead,

Schema: map[string]*schema.Schema{
"filter": ec2CustomFiltersSchema(),
"id": {
Type: schema.TypeString,
Optional: true,
},
"peer_account_id": {
Type: schema.TypeString,
Computed: true,
},
"peer_region": {
Type: schema.TypeString,
Computed: true,
},
"peer_transit_gateway_id": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchemaComputed(),
"transit_gateway_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceAwsEc2TransitGatewayPeeringAttachmentRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

input := &ec2.DescribeTransitGatewayPeeringAttachmentsInput{}

if v, ok := d.GetOk("id"); ok {
input.TransitGatewayAttachmentIds = aws.StringSlice([]string{v.(string)})
}

input.Filters = buildEC2CustomFilterList(d.Get("filter").(*schema.Set))
if v := d.Get("tags").(map[string]interface{}); len(v) > 0 {
input.Filters = append(input.Filters, ec2TagFiltersFromMap(v)...)
}
if len(input.Filters) == 0 {
// Don't send an empty filters list; the EC2 API won't accept it.
input.Filters = nil
}

log.Printf("[DEBUG] Reading EC2 Transit Gateway Peering Attachments: %s", input)
output, err := conn.DescribeTransitGatewayPeeringAttachments(input)

if err != nil {
return fmt.Errorf("error reading EC2 Transit Gateway Peering Attachments: %s", err)
}

if output == nil || len(output.TransitGatewayPeeringAttachments) == 0 {
return errors.New("error reading EC2 Transit Gateway Peering Attachment: no results found")
}

if len(output.TransitGatewayPeeringAttachments) > 1 {
return errors.New("error reading EC2 Transit Gateway Peering Attachment: multiple results found, try adjusting search criteria")
}

transitGatewayPeeringAttachment := output.TransitGatewayPeeringAttachments[0]

if transitGatewayPeeringAttachment == nil {
return errors.New("error reading EC2 Transit Gateway Peering Attachment: empty result")
}

local := transitGatewayPeeringAttachment.RequesterTgwInfo
peer := transitGatewayPeeringAttachment.AccepterTgwInfo

if aws.StringValue(transitGatewayPeeringAttachment.AccepterTgwInfo.OwnerId) == meta.(*AWSClient).accountid && aws.StringValue(transitGatewayPeeringAttachment.AccepterTgwInfo.Region) == meta.(*AWSClient).region {
local = transitGatewayPeeringAttachment.AccepterTgwInfo
peer = transitGatewayPeeringAttachment.RequesterTgwInfo
}

d.Set("peer_account_id", peer.OwnerId)
d.Set("peer_region", peer.Region)
d.Set("peer_transit_gateway_id", peer.TransitGatewayId)
d.Set("transit_gateway_id", local.TransitGatewayId)

if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(transitGatewayPeeringAttachment.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}

d.SetId(aws.StringValue(transitGatewayPeeringAttachment.TransitGatewayAttachmentId))

return nil
}
211 changes: 211 additions & 0 deletions aws/data_source_aws_ec2_transit_gateway_peering_attachment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_Filter_sameAccount(t *testing.T) {
var providers []*schema.Provider
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.aws_ec2_transit_gateway_peering_attachment.test"
resourceName := "aws_ec2_transit_gateway_peering_attachment.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSEc2TransitGateway(t)
testAccMultipleRegionsPreCheck(t)
testAccAlternateRegionPreCheck(t)
},
ProviderFactories: testAccProviderFactories(&providers),
CheckDestroy: testAccCheckAWSEc2TransitGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigFilter_sameAccount(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, "peer_account_id", dataSourceName, "peer_account_id"),
resource.TestCheckResourceAttrPair(resourceName, "peer_region", dataSourceName, "peer_region"),
resource.TestCheckResourceAttrPair(resourceName, "peer_transit_gateway_id", dataSourceName, "peer_transit_gateway_id"),
resource.TestCheckResourceAttrPair(resourceName, "tags.%", dataSourceName, "tags.%"),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", dataSourceName, "transit_gateway_id"),
),
},
},
})
}
func TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_Filter_differentAccount(t *testing.T) {
var providers []*schema.Provider
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.aws_ec2_transit_gateway_peering_attachment.test"
resourceName := "aws_ec2_transit_gateway_peering_attachment.test"
transitGatewayResourceName := "aws_ec2_transit_gateway.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSEc2TransitGateway(t)
testAccMultipleRegionsPreCheck(t)
testAccAlternateRegionPreCheck(t)
},
ProviderFactories: testAccProviderFactories(&providers),
CheckDestroy: testAccCheckAWSEc2TransitGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigFilter_differentAccount(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "peer_region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(transitGatewayResourceName, "owner_id", dataSourceName, "peer_account_id"),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", dataSourceName, "peer_transit_gateway_id"),
resource.TestCheckResourceAttrPair(resourceName, "peer_transit_gateway_id", dataSourceName, "transit_gateway_id"),
),
},
},
})
}
func TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_ID_sameAccount(t *testing.T) {
var providers []*schema.Provider
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.aws_ec2_transit_gateway_peering_attachment.test"
resourceName := "aws_ec2_transit_gateway_peering_attachment.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSEc2TransitGateway(t)
testAccMultipleRegionsPreCheck(t)
testAccAlternateRegionPreCheck(t)
},
ProviderFactories: testAccProviderFactories(&providers),
CheckDestroy: testAccCheckAWSEc2TransitGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigID_sameAccount(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, "peer_account_id", dataSourceName, "peer_account_id"),
resource.TestCheckResourceAttrPair(resourceName, "peer_region", dataSourceName, "peer_region"),
resource.TestCheckResourceAttrPair(resourceName, "peer_transit_gateway_id", dataSourceName, "peer_transit_gateway_id"),
resource.TestCheckResourceAttrPair(resourceName, "tags.%", dataSourceName, "tags.%"),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", dataSourceName, "transit_gateway_id"),
),
},
},
})
}
func TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_ID_differentAccount(t *testing.T) {
var providers []*schema.Provider
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.aws_ec2_transit_gateway_peering_attachment.test"
resourceName := "aws_ec2_transit_gateway_peering_attachment.test"
transitGatewayResourceName := "aws_ec2_transit_gateway.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSEc2TransitGateway(t)
testAccMultipleRegionsPreCheck(t)
testAccAlternateRegionPreCheck(t)
},
ProviderFactories: testAccProviderFactories(&providers),
CheckDestroy: testAccCheckAWSEc2TransitGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigID_differentAccount(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "peer_region", testAccGetRegion()),
resource.TestCheckResourceAttrPair(transitGatewayResourceName, "owner_id", dataSourceName, "peer_account_id"),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", dataSourceName, "peer_transit_gateway_id"),
resource.TestCheckResourceAttrPair(resourceName, "peer_transit_gateway_id", dataSourceName, "transit_gateway_id"),
),
},
},
})
}
func TestAccAWSEc2TransitGatewayPeeringAttachmentDataSource_Tags(t *testing.T) {
var providers []*schema.Provider
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.aws_ec2_transit_gateway_peering_attachment.test"
resourceName := "aws_ec2_transit_gateway_peering_attachment.test"
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
testAccPreCheckAWSEc2TransitGateway(t)
testAccMultipleRegionsPreCheck(t)
testAccAlternateRegionPreCheck(t)
},
ProviderFactories: testAccProviderFactories(&providers),
CheckDestroy: testAccCheckAWSEc2TransitGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigTags_sameAccount(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, "peer_account_id", dataSourceName, "peer_account_id"),
resource.TestCheckResourceAttrPair(resourceName, "peer_region", dataSourceName, "peer_region"),
resource.TestCheckResourceAttrPair(resourceName, "peer_transit_gateway_id", dataSourceName, "peer_transit_gateway_id"),
resource.TestCheckResourceAttrPair(resourceName, "tags.%", dataSourceName, "tags.%"),
resource.TestCheckResourceAttrPair(resourceName, "transit_gateway_id", dataSourceName, "transit_gateway_id"),
),
},
},
})
}

func testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigFilter_sameAccount(rName string) string {
return composeConfig(
testAccAWSEc2TransitGatewayPeeringAttachmentConfigBasic_sameAccount(rName),
fmt.Sprintf(`
data "aws_ec2_transit_gateway_peering_attachment" "test" {
filter {
name = "transit-gateway-attachment-id"
values = ["${aws_ec2_transit_gateway_peering_attachment.test.id}"]
}
}
`))
}

func testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigID_sameAccount(rName string) string {
return composeConfig(
testAccAWSEc2TransitGatewayPeeringAttachmentConfigBasic_sameAccount(rName),
fmt.Sprintf(`
data "aws_ec2_transit_gateway_peering_attachment" "test" {
id = "${aws_ec2_transit_gateway_peering_attachment.test.id}"
}
`))
}

func testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigTags_sameAccount(rName string) string {
return composeConfig(
testAccAWSEc2TransitGatewayPeeringAttachmentConfigTags1_sameAccount(rName, "Name", rName),
fmt.Sprintf(`
data "aws_ec2_transit_gateway_peering_attachment" "test" {
tags = {
Name = "${aws_ec2_transit_gateway_peering_attachment.test.tags["Name"]}"
}
}
`))
}

func testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigFilter_differentAccount(rName string) string {
return composeConfig(
testAccAWSEc2TransitGatewayPeeringAttachmentConfigBasic_differentAccount(rName),
fmt.Sprintf(`
data "aws_ec2_transit_gateway_peering_attachment" "test" {
provider = "aws.alternate"
filter {
name = "transit-gateway-attachment-id"
values = ["${aws_ec2_transit_gateway_peering_attachment.test.id}"]
}
}
`))
}

func testAccAWSEc2TransitGatewayPeeringAttachmentDataSourceConfigID_differentAccount(rName string) string {
return composeConfig(
testAccAWSEc2TransitGatewayPeeringAttachmentConfigBasic_differentAccount(rName),
fmt.Sprintf(`
data "aws_ec2_transit_gateway_peering_attachment" "test" {
provider = "aws.alternate"
id = "${aws_ec2_transit_gateway_peering_attachment.test.id}"
}
`))
}
34 changes: 30 additions & 4 deletions aws/ec2_transit_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,10 @@ func ec2TransitGatewayPeeringAttachmentRefreshFunc(conn *ec2.EC2, transitGateway
return nil, ec2.TransitGatewayAttachmentStateDeleted, nil
}

if aws.StringValue(transitGatewayPeeringAttachment.State) == ec2.TransitGatewayAttachmentStateFailed && transitGatewayPeeringAttachment.Status != nil {
return transitGatewayPeeringAttachment, aws.StringValue(transitGatewayPeeringAttachment.State), fmt.Errorf("%s: %s", aws.StringValue(transitGatewayPeeringAttachment.Status.Code), aws.StringValue(transitGatewayPeeringAttachment.Status.Message))
}

return transitGatewayPeeringAttachment, aws.StringValue(transitGatewayPeeringAttachment.State), nil
}
}
Expand Down Expand Up @@ -615,16 +619,38 @@ func waitForEc2TransitGatewayPeeringAttachmentAcceptance(conn *ec2.EC2, transitG
return err
}

func waitForEc2TransitGatewayPeeringAttachmentCreation(conn *ec2.EC2, transitGatewayAttachmentID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{
ec2.TransitGatewayAttachmentStateFailing,
ec2.TransitGatewayAttachmentStatePending,
"initiatingRequest", // No ENUM currently exists in the SDK for the state given by AWS
},
Target: []string{
ec2.TransitGatewayAttachmentStateAvailable,
ec2.TransitGatewayAttachmentStatePendingAcceptance,
},
Refresh: ec2TransitGatewayPeeringAttachmentRefreshFunc(conn, transitGatewayAttachmentID),
Timeout: 10 * time.Minute,
}

log.Printf("[DEBUG] Waiting for EC2 Transit Gateway Peering Attachment (%s) availability", transitGatewayAttachmentID)
_, err := stateConf.WaitForState()

return err
}

func waitForEc2TransitGatewayPeeringAttachmentDeletion(conn *ec2.EC2, transitGatewayAttachmentID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{
ec2.TransitGatewayAttachmentStateAvailable,
ec2.TransitGatewayAttachmentStateDeleting,
ec2.TransitGatewayAttachmentStatePendingAcceptance,
ec2.TransitGatewayAttachmentStateRejected,
},
Target: []string{ec2.TransitGatewayAttachmentStateDeleted},
Refresh: ec2TransitGatewayVpcAttachmentRefreshFunc(conn, transitGatewayAttachmentID),
Timeout: 10 * time.Minute,
NotFoundChecks: 1,
Target: []string{ec2.TransitGatewayAttachmentStateDeleted},
Refresh: ec2TransitGatewayPeeringAttachmentRefreshFunc(conn, transitGatewayAttachmentID),
Timeout: 10 * time.Minute,
}

log.Printf("[DEBUG] Waiting for EC2 Transit Gateway Peering Attachment (%s) deletion", transitGatewayAttachmentID)
Expand Down
2 changes: 2 additions & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ func Provider() terraform.ResourceProvider {
"aws_ebs_volume": dataSourceAwsEbsVolume(),
"aws_ec2_transit_gateway": dataSourceAwsEc2TransitGateway(),
"aws_ec2_transit_gateway_dx_gateway_attachment": dataSourceAwsEc2TransitGatewayDxGatewayAttachment(),
"aws_ec2_transit_gateway_peering_attachment": dataSourceAwsEc2TransitGatewayPeeringAttachment(),
"aws_ec2_transit_gateway_route_table": dataSourceAwsEc2TransitGatewayRouteTable(),
"aws_ec2_transit_gateway_vpc_attachment": dataSourceAwsEc2TransitGatewayVpcAttachment(),
"aws_ec2_transit_gateway_vpn_attachment": dataSourceAwsEc2TransitGatewayVpnAttachment(),
Expand Down Expand Up @@ -484,6 +485,7 @@ func Provider() terraform.ResourceProvider {
"aws_ec2_client_vpn_network_association": resourceAwsEc2ClientVpnNetworkAssociation(),
"aws_ec2_fleet": resourceAwsEc2Fleet(),
"aws_ec2_transit_gateway": resourceAwsEc2TransitGateway(),
"aws_ec2_transit_gateway_peering_attachment": resourceAwsEc2TransitGatewayPeeringAttachment(),
"aws_ec2_transit_gateway_peering_attachment_accepter": resourceAwsEc2TransitGatewayPeeringAttachmentAccepter(),
"aws_ec2_transit_gateway_route": resourceAwsEc2TransitGatewayRoute(),
"aws_ec2_transit_gateway_route_table": resourceAwsEc2TransitGatewayRouteTable(),
Expand Down
4 changes: 4 additions & 0 deletions aws/resource_aws_ec2_transit_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ func resourceAwsEc2TransitGatewayDelete(d *schema.ResourceData, meta interface{}
return resource.RetryableError(err)
}

if isAWSErr(err, "IncorrectState", "has non-deleted Transit Gateway Cross Region Peering Attachments") {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}
Expand Down
Loading

0 comments on commit 4cee185

Please sign in to comment.