Skip to content
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

New resource: aws_ec2_transit_gateway_vpc_attachment_accepter #8679

Merged
merged 6 commits into from
May 27, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions aws/ec2_transit_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,24 @@ func waitForEc2TransitGatewayRouteTableAssociationDeletion(conn *ec2.EC2, transi
return err
}

func waitForEc2TransitGatewayRouteTableAttachmentCreation(conn *ec2.EC2, transitGatewayAttachmentID string) error {
func waitForEc2TransitGatewayVpcAttachmentAcceptance(conn *ec2.EC2, transitGatewayAttachmentID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{
ec2.TransitGatewayAttachmentStatePending,
ec2.TransitGatewayAttachmentStatePendingAcceptance,
},
Target: []string{ec2.TransitGatewayAttachmentStateAvailable},
Refresh: ec2TransitGatewayVpcAttachmentRefreshFunc(conn, transitGatewayAttachmentID),
Timeout: 10 * time.Minute,
}

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

return err
}

func waitForEc2TransitGatewayVpcAttachmentCreation(conn *ec2.EC2, transitGatewayAttachmentID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{ec2.TransitGatewayAttachmentStatePending},
Target: []string{
Expand All @@ -558,7 +575,7 @@ func waitForEc2TransitGatewayRouteTableAttachmentCreation(conn *ec2.EC2, transit
return err
}

func waitForEc2TransitGatewayRouteTableAttachmentDeletion(conn *ec2.EC2, transitGatewayAttachmentID string) error {
func waitForEc2TransitGatewayVpcAttachmentDeletion(conn *ec2.EC2, transitGatewayAttachmentID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{
ec2.TransitGatewayAttachmentStateAvailable,
Expand All @@ -580,7 +597,7 @@ func waitForEc2TransitGatewayRouteTableAttachmentDeletion(conn *ec2.EC2, transit
return err
}

func waitForEc2TransitGatewayRouteTableAttachmentUpdate(conn *ec2.EC2, transitGatewayAttachmentID string) error {
func waitForEc2TransitGatewayVpcAttachmentUpdate(conn *ec2.EC2, transitGatewayAttachmentID string) error {
stateConf := &resource.StateChangeConf{
Pending: []string{ec2.TransitGatewayAttachmentStateModifying},
Target: []string{ec2.TransitGatewayAttachmentStateAvailable},
Expand Down
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ func Provider() terraform.ResourceProvider {
"aws_ec2_transit_gateway_route_table_association": resourceAwsEc2TransitGatewayRouteTableAssociation(),
"aws_ec2_transit_gateway_route_table_propagation": resourceAwsEc2TransitGatewayRouteTablePropagation(),
"aws_ec2_transit_gateway_vpc_attachment": resourceAwsEc2TransitGatewayVpcAttachment(),
"aws_ec2_transit_gateway_vpc_attachment_accepter": resourceAwsEc2TransitGatewayVpcAttachmentAccepter(),
"aws_ecr_lifecycle_policy": resourceAwsEcrLifecyclePolicy(),
"aws_ecr_repository": resourceAwsEcrRepository(),
"aws_ecr_repository_policy": resourceAwsEcrRepositoryPolicy(),
Expand Down
6 changes: 3 additions & 3 deletions aws/resource_aws_ec2_transit_gateway_vpc_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func resourceAwsEc2TransitGatewayVpcAttachmentCreate(d *schema.ResourceData, met

d.SetId(aws.StringValue(output.TransitGatewayVpcAttachment.TransitGatewayAttachmentId))

if err := waitForEc2TransitGatewayRouteTableAttachmentCreation(conn, d.Id()); err != nil {
bflad marked this conversation as resolved.
Show resolved Hide resolved
if err := waitForEc2TransitGatewayVpcAttachmentCreation(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EC2 Transit Gateway VPC Attachment (%s) availability: %s", d.Id(), err)
}

Expand Down Expand Up @@ -238,7 +238,7 @@ func resourceAwsEc2TransitGatewayVpcAttachmentUpdate(d *schema.ResourceData, met
return fmt.Errorf("error modifying EC2 Transit Gateway VPC Attachment (%s): %s", d.Id(), err)
}

if err := waitForEc2TransitGatewayRouteTableAttachmentUpdate(conn, d.Id()); err != nil {
bflad marked this conversation as resolved.
Show resolved Hide resolved
if err := waitForEc2TransitGatewayVpcAttachmentUpdate(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EC2 Transit Gateway VPC Attachment (%s) update: %s", d.Id(), err)
}
}
Expand Down Expand Up @@ -295,7 +295,7 @@ func resourceAwsEc2TransitGatewayVpcAttachmentDelete(d *schema.ResourceData, met
return fmt.Errorf("error deleting EC2 Transit Gateway VPC Attachment: %s", err)
}

if err := waitForEc2TransitGatewayRouteTableAttachmentDeletion(conn, d.Id()); err != nil {
bflad marked this conversation as resolved.
Show resolved Hide resolved
if err := waitForEc2TransitGatewayVpcAttachmentDeletion(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EC2 Transit Gateway VPC Attachment (%s) deletion: %s", d.Id(), err)
}

Expand Down
226 changes: 226 additions & 0 deletions aws/resource_aws_ec2_transit_gateway_vpc_attachment_accepter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsEc2TransitGatewayVpcAttachmentAccepter() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEc2TransitGatewayVpcAttachmentAccepterCreate,
Read: resourceAwsEc2TransitGatewayVpcAttachmentAccepterRead,
Update: resourceAwsEc2TransitGatewayVpcAttachmentAccepterUpdate,
Delete: resourceAwsEc2TransitGatewayVpcAttachmentAccepterDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"dns_support": {
Type: schema.TypeString,
Computed: true,
},
"ipv6_support": {
Type: schema.TypeString,
Computed: true,
},
"subnet_ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"tags": tagsSchema(),
"transit_gateway_attachment_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"transit_gateway_default_route_table_association": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"transit_gateway_default_route_table_propagation": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"transit_gateway_id": {
Type: schema.TypeString,
Computed: true,
},
"vpc_id": {
Type: schema.TypeString,
Computed: true,
},
"vpc_owner_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

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

input := &ec2.AcceptTransitGatewayVpcAttachmentInput{
TransitGatewayAttachmentId: aws.String(d.Get("transit_gateway_attachment_id").(string)),
}

log.Printf("[DEBUG] Accepting EC2 Transit Gateway VPC Attachment: %s", input)
output, err := conn.AcceptTransitGatewayVpcAttachment(input)
if err != nil {
return fmt.Errorf("error accepting EC2 Transit Gateway VPC Attachment: %s", err)
}

d.SetId(aws.StringValue(output.TransitGatewayVpcAttachment.TransitGatewayAttachmentId))
transitGatewayID := aws.StringValue(output.TransitGatewayVpcAttachment.TransitGatewayId)

if err := waitForEc2TransitGatewayVpcAttachmentAcceptance(conn, d.Id()); err != nil {
return fmt.Errorf("error waiting for EC2 Transit Gateway VPC Attachment (%s) availability: %s", d.Id(), err)
}

if err := setTags(conn, d); err != nil {
return fmt.Errorf("error updating EC2 Transit Gateway VPC Attachment (%s) tags: %s", d.Id(), err)
}

transitGateway, err := ec2DescribeTransitGateway(conn, transitGatewayID)
if err != nil {
return fmt.Errorf("error describing EC2 Transit Gateway (%s): %s", transitGatewayID, err)
}

if transitGateway.Options == nil {
return fmt.Errorf("error describing EC2 Transit Gateway (%s): missing options", transitGatewayID)
}

if err := ec2TransitGatewayRouteTableAssociationUpdate(conn, aws.StringValue(transitGateway.Options.AssociationDefaultRouteTableId), d.Id(), d.Get("transit_gateway_default_route_table_association").(bool)); err != nil {
return fmt.Errorf("error updating EC2 Transit Gateway Attachment (%s) Route Table (%s) association: %s", d.Id(), aws.StringValue(transitGateway.Options.AssociationDefaultRouteTableId), err)
}

if err := ec2TransitGatewayRouteTablePropagationUpdate(conn, aws.StringValue(transitGateway.Options.PropagationDefaultRouteTableId), d.Id(), d.Get("transit_gateway_default_route_table_propagation").(bool)); err != nil {
return fmt.Errorf("error updating EC2 Transit Gateway Attachment (%s) Route Table (%s) propagation: %s", d.Id(), aws.StringValue(transitGateway.Options.PropagationDefaultRouteTableId), err)
}

return resourceAwsEc2TransitGatewayVpcAttachmentAccepterRead(d, meta)
}

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

transitGatewayVpcAttachment, err := ec2DescribeTransitGatewayVpcAttachment(conn, d.Id())

if isAWSErr(err, "InvalidTransitGatewayAttachmentID.NotFound", "") {
log.Printf("[WARN] EC2 Transit Gateway VPC Attachment (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

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

if transitGatewayVpcAttachment == nil {
log.Printf("[WARN] EC2 Transit Gateway VPC Attachment (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if aws.StringValue(transitGatewayVpcAttachment.State) == ec2.TransitGatewayAttachmentStateDeleting || aws.StringValue(transitGatewayVpcAttachment.State) == ec2.TransitGatewayAttachmentStateDeleted {
log.Printf("[WARN] EC2 Transit Gateway VPC Attachment (%s) in deleted state (%s), removing from state", d.Id(), aws.StringValue(transitGatewayVpcAttachment.State))
d.SetId("")
return nil
}

transitGatewayID := aws.StringValue(transitGatewayVpcAttachment.TransitGatewayId)
transitGateway, err := ec2DescribeTransitGateway(conn, transitGatewayID)
if err != nil {
return fmt.Errorf("error describing EC2 Transit Gateway (%s): %s", transitGatewayID, err)
}

if transitGateway.Options == nil {
return fmt.Errorf("error describing EC2 Transit Gateway (%s): missing options", transitGatewayID)
}

transitGatewayAssociationDefaultRouteTableID := aws.StringValue(transitGateway.Options.AssociationDefaultRouteTableId)
transitGatewayDefaultRouteTableAssociation, err := ec2DescribeTransitGatewayRouteTableAssociation(conn, transitGatewayAssociationDefaultRouteTableID, d.Id())
if err != nil {
return fmt.Errorf("error determining EC2 Transit Gateway Attachment (%s) association to Route Table (%s): %s", d.Id(), transitGatewayAssociationDefaultRouteTableID, err)
}

transitGatewayPropagationDefaultRouteTableID := aws.StringValue(transitGateway.Options.PropagationDefaultRouteTableId)
transitGatewayDefaultRouteTablePropagation, err := ec2DescribeTransitGatewayRouteTablePropagation(conn, transitGatewayPropagationDefaultRouteTableID, d.Id())
if err != nil {
return fmt.Errorf("error determining EC2 Transit Gateway Attachment (%s) propagation to Route Table (%s): %s", d.Id(), transitGatewayPropagationDefaultRouteTableID, err)
}

if transitGatewayVpcAttachment.Options == nil {
return fmt.Errorf("error reading EC2 Transit Gateway VPC Attachment (%s): missing options", d.Id())
}

d.Set("dns_support", transitGatewayVpcAttachment.Options.DnsSupport)
d.Set("ipv6_support", transitGatewayVpcAttachment.Options.Ipv6Support)

if err := d.Set("subnet_ids", aws.StringValueSlice(transitGatewayVpcAttachment.SubnetIds)); err != nil {
return fmt.Errorf("error setting subnet_ids: %s", err)
}

if err := d.Set("tags", tagsToMap(transitGatewayVpcAttachment.Tags)); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}

d.Set("transit_gateway_attachment_id", aws.StringValue(transitGatewayVpcAttachment.TransitGatewayAttachmentId))
d.Set("transit_gateway_default_route_table_association", (transitGatewayDefaultRouteTableAssociation != nil))
d.Set("transit_gateway_default_route_table_propagation", (transitGatewayDefaultRouteTablePropagation != nil))
d.Set("transit_gateway_id", aws.StringValue(transitGatewayVpcAttachment.TransitGatewayId))
d.Set("vpc_id", aws.StringValue(transitGatewayVpcAttachment.VpcId))
d.Set("vpc_owner_id", aws.StringValue(transitGatewayVpcAttachment.VpcOwnerId))

return nil
}

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

if d.HasChange("transit_gateway_default_route_table_association") || d.HasChange("transit_gateway_default_route_table_propagation") {
transitGatewayID := d.Get("transit_gateway_id").(string)

transitGateway, err := ec2DescribeTransitGateway(conn, transitGatewayID)
if err != nil {
return fmt.Errorf("error describing EC2 Transit Gateway (%s): %s", transitGatewayID, err)
}

if transitGateway.Options == nil {
return fmt.Errorf("error describing EC2 Transit Gateway (%s): missing options", transitGatewayID)
}

if d.HasChange("transit_gateway_default_route_table_association") {
if err := ec2TransitGatewayRouteTableAssociationUpdate(conn, aws.StringValue(transitGateway.Options.AssociationDefaultRouteTableId), d.Id(), d.Get("transit_gateway_default_route_table_association").(bool)); err != nil {
return fmt.Errorf("error updating EC2 Transit Gateway Attachment (%s) Route Table (%s) association: %s", d.Id(), aws.StringValue(transitGateway.Options.AssociationDefaultRouteTableId), err)
}
}

if d.HasChange("transit_gateway_default_route_table_propagation") {
if err := ec2TransitGatewayRouteTablePropagationUpdate(conn, aws.StringValue(transitGateway.Options.PropagationDefaultRouteTableId), d.Id(), d.Get("transit_gateway_default_route_table_propagation").(bool)); err != nil {
return fmt.Errorf("error updating EC2 Transit Gateway Attachment (%s) Route Table (%s) propagation: %s", d.Id(), aws.StringValue(transitGateway.Options.PropagationDefaultRouteTableId), err)
}
}
}

if d.HasChange("tags") {
if err := setTags(conn, d); err != nil {
return fmt.Errorf("error updating EC2 Transit Gateway VPC Attachment (%s) tags: %s", d.Id(), err)
}
}

return nil
}

func resourceAwsEc2TransitGatewayVpcAttachmentAccepterDelete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[WARN] Will not delete EC2 Transit Gateway VPC Attachment. Terraform will remove this resource from the state file, however resources may remain.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The accepting side should be able to call DeleteTransitGatewayVpcAttachment here to break the attachment. 👍

return nil
}
Loading