diff --git a/.changelog/44616.txt b/.changelog/44616.txt new file mode 100644 index 000000000000..9db556601697 --- /dev/null +++ b/.changelog/44616.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ec2_instance_connect_endpoint: Add `ip_address_type` argument +``` diff --git a/internal/service/ec2/ec2_instance_connect_endpoint.go b/internal/service/ec2/ec2_instance_connect_endpoint.go index d0fdca06db7c..0d9c6cd0b1b5 100644 --- a/internal/service/ec2/ec2_instance_connect_endpoint.go +++ b/internal/service/ec2/ec2_instance_connect_endpoint.go @@ -78,6 +78,14 @@ func (r *instanceConnectEndpointResource) Schema(ctx context.Context, req resour }, }, names.AttrID: framework.IDAttribute(), + names.AttrIPAddressType: schema.StringAttribute{ + CustomType: fwtypes.StringEnumType[awstypes.IpAddressType](), + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, "network_interface_ids": schema.ListAttribute{ CustomType: fwtypes.ListOfStringType, Computed: true, @@ -261,18 +269,19 @@ func (r *instanceConnectEndpointResource) Delete(ctx context.Context, request re // See https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Ec2InstanceConnectEndpoint.html. type instanceConnectEndpointResourceModel struct { framework.WithRegionModel - InstanceConnectEndpointARN types.String `tfsdk:"arn"` - AvailabilityZone types.String `tfsdk:"availability_zone"` - DNSName types.String `tfsdk:"dns_name"` - FipsDnsName types.String `tfsdk:"fips_dns_name"` - InstanceConnectEndpointID types.String `tfsdk:"id"` - NetworkInterfaceIDs fwtypes.ListOfString `tfsdk:"network_interface_ids"` - OwnerID types.String `tfsdk:"owner_id"` - PreserveClientIP types.Bool `tfsdk:"preserve_client_ip"` - SecurityGroupIDs fwtypes.SetOfString `tfsdk:"security_group_ids"` - SubnetId types.String `tfsdk:"subnet_id"` - Tags tftags.Map `tfsdk:"tags"` - TagsAll tftags.Map `tfsdk:"tags_all"` - Timeouts timeouts.Value `tfsdk:"timeouts"` - VpcId types.String `tfsdk:"vpc_id"` + InstanceConnectEndpointARN types.String `tfsdk:"arn"` + AvailabilityZone types.String `tfsdk:"availability_zone"` + DNSName types.String `tfsdk:"dns_name"` + FipsDnsName types.String `tfsdk:"fips_dns_name"` + InstanceConnectEndpointID types.String `tfsdk:"id"` + IPAddressType fwtypes.StringEnum[awstypes.IpAddressType] `tfsdk:"ip_address_type"` + NetworkInterfaceIDs fwtypes.ListOfString `tfsdk:"network_interface_ids"` + OwnerID types.String `tfsdk:"owner_id"` + PreserveClientIP types.Bool `tfsdk:"preserve_client_ip"` + SecurityGroupIDs fwtypes.SetOfString `tfsdk:"security_group_ids"` + SubnetId types.String `tfsdk:"subnet_id"` + Tags tftags.Map `tfsdk:"tags"` + TagsAll tftags.Map `tfsdk:"tags_all"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + VpcId types.String `tfsdk:"vpc_id"` } diff --git a/internal/service/ec2/ec2_instance_connect_endpoint_test.go b/internal/service/ec2/ec2_instance_connect_endpoint_test.go index df304ca02bcb..109f198ba9b4 100644 --- a/internal/service/ec2/ec2_instance_connect_endpoint_test.go +++ b/internal/service/ec2/ec2_instance_connect_endpoint_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/YakDriver/regexache" + awstypes "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/hashicorp/aws-sdk-go-base/v2/endpoints" sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -40,6 +41,7 @@ func TestAccEC2InstanceConnectEndpoint_basic(t *testing.T) { acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "ec2", regexache.MustCompile(`instance-connect-endpoint/.+`)), resource.TestCheckResourceAttrSet(resourceName, names.AttrAvailabilityZone), resource.TestCheckResourceAttrSet(resourceName, names.AttrDNSName), + resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, string(awstypes.IpAddressTypeIpv4)), acctest.CheckResourceAttrGreaterThanOrEqualValue(resourceName, "network_interface_ids.#", 1), acctest.CheckResourceAttrAccountID(ctx, resourceName, names.AttrOwnerID), resource.TestCheckResourceAttr(resourceName, "preserve_client_ip", acctest.CtTrue), @@ -168,6 +170,87 @@ func TestAccEC2InstanceConnectEndpoint_securityGroupIDs(t *testing.T) { }) } +func TestAccEC2InstanceConnectEndpoint_ipAddressTypeIPv4(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_ec2_instance_connect_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckInstanceConnectEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccInstanceConnectEndpointConfig_ipAddressType(rName, string(awstypes.IpAddressTypeIpv4), true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckInstanceConnectEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, string(awstypes.IpAddressTypeIpv4)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccEC2InstanceConnectEndpoint_ipAddressTypeIPv6(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_ec2_instance_connect_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckInstanceConnectEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccInstanceConnectEndpointConfig_ipAddressType(rName, string(awstypes.IpAddressTypeIpv6), false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckInstanceConnectEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, string(awstypes.IpAddressTypeIpv6)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccEC2InstanceConnectEndpoint_ipAddressTypeDualStack(t *testing.T) { + ctx := acctest.Context(t) + resourceName := "aws_ec2_instance_connect_endpoint.test" + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckInstanceConnectEndpointDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccInstanceConnectEndpointConfig_ipAddressType(rName, string(awstypes.IpAddressTypeDualstack), false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckInstanceConnectEndpointExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, names.AttrIPAddressType, string(awstypes.IpAddressTypeDualstack)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccEC2InstanceConnectEndpoint_fipsRegion(t *testing.T) { ctx := acctest.Context(t) resourceName := "aws_ec2_instance_connect_endpoint.test" @@ -320,3 +403,17 @@ resource "aws_ec2_instance_connect_endpoint" "test" { } `, rName)) } + +func testAccInstanceConnectEndpointConfig_ipAddressType(rName, ipAddressType string, preserveClientIP bool) string { + return acctest.ConfigCompose(acctest.ConfigVPCWithSubnetsIPv6(rName, 1), fmt.Sprintf(` +resource "aws_ec2_instance_connect_endpoint" "test" { + preserve_client_ip = %[3]t + subnet_id = aws_subnet.test[0].id + ip_address_type = %[2]q + + tags = { + Name = %[1]q + } +} +`, rName, ipAddressType, preserveClientIP)) +} diff --git a/website/docs/r/ec2_instance_connect_endpoint.html.markdown b/website/docs/r/ec2_instance_connect_endpoint.html.markdown index fd8de29e1fc1..9c7cf3822aef 100644 --- a/website/docs/r/ec2_instance_connect_endpoint.html.markdown +++ b/website/docs/r/ec2_instance_connect_endpoint.html.markdown @@ -23,6 +23,7 @@ resource "aws_ec2_instance_connect_endpoint" "example" { This resource supports the following arguments: * `region` - (Optional) Region where this resource will be [managed](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints). Defaults to the Region set in the [provider configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#aws-configuration-reference). +* `ip_address_type` - (Optional) IP address type of the endpoint. Valid values are `ipv4`, `ipv6`, and `dualstack`. The default value is determined by the IP address type of the subnet. See the [AWS documentation](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateInstanceConnectEndpoint.html) for more details. * `preserve_client_ip` - (Optional) Indicates whether your client's IP address is preserved as the source. Default: `true`. * `security_group_ids` - (Optional) One or more security groups to associate with the endpoint. If you don't specify a security group, the default security group for the VPC will be associated with the endpoint. * `subnet_id` - (Required) The ID of the subnet in which to create the EC2 Instance Connect Endpoint.