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_vpc_endpoint_connection_accepter #19083

Merged
3 changes: 3 additions & 0 deletions .changelog/19083.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_vpc_endpoint_connection_accepter
```
1 change: 1 addition & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,7 @@ func Provider() *schema.Provider {
"aws_vpc_dhcp_options": ec2.ResourceVPCDHCPOptions(),
"aws_vpc_dhcp_options_association": ec2.ResourceVPCDHCPOptionsAssociation(),
"aws_vpc_endpoint": ec2.ResourceVPCEndpoint(),
"aws_vpc_endpoint_connection_accepter": ec2.ResourceVPCEndpointConnectionAccepter(),
"aws_vpc_endpoint_connection_notification": ec2.ResourceVPCEndpointConnectionNotification(),
"aws_vpc_endpoint_route_table_association": ec2.ResourceVPCEndpointRouteTableAssociation(),
"aws_vpc_endpoint_service": ec2.ResourceVPCEndpointService(),
Expand Down
45 changes: 45 additions & 0 deletions internal/service/ec2/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -1349,3 +1349,48 @@ func FindPlacementGroupByName(conn *ec2.EC2, name string) (*ec2.PlacementGroup,

return placementGroup, nil
}

func FindVPCEndpointConnectionByServiceIDAndVPCEndpointID(conn *ec2.EC2, serviceID, vpcEndpointID string) (*ec2.VpcEndpointConnection, error) {
input := &ec2.DescribeVpcEndpointConnectionsInput{
Filters: BuildAttributeFilterList(map[string]string{
"service-id": serviceID,
// "InvalidFilter: The filter vpc-endpoint-id is invalid"
// "vpc-endpoint-id ": vpcEndpointID,
}),
}

var output *ec2.VpcEndpointConnection

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

for _, v := range page.VpcEndpointConnections {
if aws.StringValue(v.VpcEndpointId) == vpcEndpointID {
output = v

return false
}
}

return !lastPage
})

if err != nil {
return nil, err
}

if output == nil {
return nil, tfresource.NewEmptyResultError(input)
}

if vpcEndpointState := aws.StringValue(output.VpcEndpointState); vpcEndpointState == VPCEndpointStateDeleted {
return nil, &resource.NotFoundError{
Message: vpcEndpointState,
LastRequest: input,
}
}

return output, nil
}
16 changes: 16 additions & 0 deletions internal/service/ec2/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -641,3 +641,19 @@ func StatusEBSSnapshotImport(conn *ec2.EC2, importTaskId string) resource.StateR
}
}
}

func statusVPCEndpointConnectionVPCEndpointState(conn *ec2.EC2, serviceID, vpcEndpointID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindVPCEndpointConnectionByServiceIDAndVPCEndpointID(conn, serviceID, vpcEndpointID)

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

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

return output, aws.StringValue(output.VpcEndpointState), nil
}
}
146 changes: 146 additions & 0 deletions internal/service/ec2/vpc_endpoint_connection_accepter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package ec2

import (
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/aws-sdk-go-base/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
)

func ResourceVPCEndpointConnectionAccepter() *schema.Resource {
return &schema.Resource{
Create: resourceVPCEndpointConnectionAccepterCreate,
Read: resourceVPCEndpointConnectionAccepterRead,
Delete: resourceVPCEndpointConnectionAccepterDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"vpc_endpoint_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vpc_endpoint_service_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vpc_endpoint_state": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceVPCEndpointConnectionAccepterCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn

serviceID := d.Get("vpc_endpoint_service_id").(string)
vpcEndpointID := d.Get("vpc_endpoint_id").(string)
id := VPCEndpointConnectionAccepterCreateResourceID(serviceID, vpcEndpointID)
input := &ec2.AcceptVpcEndpointConnectionsInput{
ServiceId: aws.String(serviceID),
VpcEndpointIds: aws.StringSlice([]string{vpcEndpointID}),
}

log.Printf("[DEBUG] Accepting VPC Endpoint Connection: %s", input)
_, err := conn.AcceptVpcEndpointConnections(input)

if err != nil {
return fmt.Errorf("error accepting VPC Endpoint Connection (%s): %w", id, err)
}

d.SetId(id)

_, err = waitVPCEndpointConnectionAccepted(conn, serviceID, vpcEndpointID, d.Timeout(schema.TimeoutCreate))

if err != nil {
return fmt.Errorf("error waiting for VPC Endpoint Connection (%s) to be accepted: %w", d.Id(), err)
}

return resourceVPCEndpointConnectionAccepterRead(d, meta)
}

func resourceVPCEndpointConnectionAccepterRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn

serviceID, vpcEndpointID, err := VPCEndpointConnectionAccepterParseResourceID(d.Id())

if err != nil {
return err
}

vpcEndpointConnection, err := FindVPCEndpointConnectionByServiceIDAndVPCEndpointID(conn, serviceID, vpcEndpointID)

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] VPC Endpoint Connection %s not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("error reading VPC Endpoint Connection (%s): %w", d.Id(), err)
}

d.Set("vpc_endpoint_id", vpcEndpointConnection.VpcEndpointId)
d.Set("vpc_endpoint_service_id", vpcEndpointConnection.ServiceId)
d.Set("vpc_endpoint_state", vpcEndpointConnection.VpcEndpointState)

return nil
}

func resourceVPCEndpointConnectionAccepterDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).EC2Conn

serviceID, vpcEndpointID, err := VPCEndpointConnectionAccepterParseResourceID(d.Id())

if err != nil {
return err
}

input := &ec2.RejectVpcEndpointConnectionsInput{
ServiceId: aws.String(serviceID),
VpcEndpointIds: aws.StringSlice([]string{vpcEndpointID}),
}

_, err = conn.RejectVpcEndpointConnections(input)

if tfawserr.ErrCodeEquals(err, ErrCodeInvalidVPCEndpointServiceIdNotFound) {
return nil
}

if err != nil {
return fmt.Errorf("error rejecting VPC Endpoint Connection (%s): %w", d.Id(), err)
}

return nil
}

const vpcEndpointConnectionAccepterResourceIDSeparator = "_"

func VPCEndpointConnectionAccepterCreateResourceID(serviceID, vpcEndpointID string) string {
parts := []string{serviceID, vpcEndpointID}
id := strings.Join(parts, vpcEndpointConnectionAccepterResourceIDSeparator)

return id
}

func VPCEndpointConnectionAccepterParseResourceID(id string) (string, string, error) {
parts := strings.Split(id, vpcEndpointConnectionAccepterResourceIDSeparator)

if len(parts) == 2 && parts[0] != "" && parts[1] != "" {
return parts[0], parts[1], nil
}

return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected VPCEndpointServiceID%[2]sVPCEndpointID", id, vpcEndpointConnectionAccepterResourceIDSeparator)
}
Loading