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

Resource aws client vpn net addl sgs #14146

Merged
merged 18 commits into from
Aug 20, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ SWEEP_DIR?=./aws
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor)
PKG_NAME=aws
TEST_COUNT?=1
ACCTEST_TIMEOUT?=120m
ACCTEST_PARALLELISM?=20

default: build
Expand Down Expand Up @@ -33,7 +34,7 @@ testacc: fmtcheck
echo "See the contributing guide for more information: https://github.com/terraform-providers/terraform-provider-aws/blob/master/docs/contributing/running-and-writing-acceptance-tests.md"; \
exit 1; \
fi
TF_ACC=1 go test ./$(PKG_NAME) -v -count $(TEST_COUNT) -parallel $(ACCTEST_PARALLELISM) $(TESTARGS) -timeout 120m
TF_ACC=1 go test ./$(PKG_NAME) -v -count $(TEST_COUNT) -parallel $(ACCTEST_PARALLELISM) $(TESTARGS) -timeout $(ACCTEST_TIMEOUT)

fmt:
@echo "==> Fixing source code with gofmt..."
Expand Down
8 changes: 7 additions & 1 deletion aws/internal/experimental/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sync

import (
"fmt"
"log"
"os"
"strconv"
"testing"
Expand Down Expand Up @@ -34,7 +35,12 @@ func (s Semaphore) Wait() {
// Notify releases a semaphore
// NOTE: this is currently an experimental feature and is likely to change. DO NOT USE.
func (s Semaphore) Notify() {
<-s
// Make the Notify non-blocking. This can happen if a Wait was never issued
select {
case <-s:
default:
log.Println("[WARN] Notifying semaphore without Wait")
}
}

// TestAccPreCheckSyncronized waits for a semaphore and skips the test if there is no capacity
Expand Down
19 changes: 19 additions & 0 deletions aws/internal/service/ec2/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ func ClientVpnAuthorizationRuleParseID(id string) (string, string, string, error
clientVpnAuthorizationRuleIDSeparator+"group-id", id)
}

const clientVpnNetworkAssociationIDSeparator = ","

func ClientVpnNetworkAssociationCreateID(endpointID, associationID string) string {
parts := []string{endpointID, associationID}
id := strings.Join(parts, clientVpnNetworkAssociationIDSeparator)
return id
}

func ClientVpnNetworkAssociationParseID(id string) (string, string, error) {
parts := strings.Split(id, clientVpnNetworkAssociationIDSeparator)
if len(parts) == 2 && parts[0] != "" && parts[1] != "" {
return parts[0], parts[1], nil
}

return "", "",
fmt.Errorf("unexpected format for ID (%q), expected endpoint-id"+clientVpnNetworkAssociationIDSeparator+
"association-id", id)
}

const clientVpnRouteIDSeparator = ","

func ClientVpnRouteCreateID(endpointID, targetSubnetID, destinationCidr string) string {
Expand Down
33 changes: 33 additions & 0 deletions aws/internal/service/ec2/waiter/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,39 @@ func ClientVpnAuthorizationRuleStatus(conn *ec2.EC2, authorizationRuleID string)
}
}

const (
ClientVpnNetworkAssociationStatusNotFound = "NotFound"

ClientVpnNetworkAssociationStatusUnknown = "Unknown"
)

func ClientVpnNetworkAssociationStatus(conn *ec2.EC2, cvnaID string, cvepID string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
result, err := conn.DescribeClientVpnTargetNetworks(&ec2.DescribeClientVpnTargetNetworksInput{
ClientVpnEndpointId: aws.String(cvepID),
AssociationIds: []*string{aws.String(cvnaID)},
})

if tfec2.ErrCodeEquals(err, tfec2.ErrCodeClientVpnAssociationIdNotFound) || tfec2.ErrCodeEquals(err, tfec2.ErrCodeClientVpnEndpointIdNotFound) {
return nil, ClientVpnNetworkAssociationStatusNotFound, nil
}
if err != nil {
return nil, ClientVpnNetworkAssociationStatusUnknown, err
}

if result == nil || len(result.ClientVpnTargetNetworks) == 0 || result.ClientVpnTargetNetworks[0] == nil {
return nil, ClientVpnNetworkAssociationStatusNotFound, nil
}

network := result.ClientVpnTargetNetworks[0]
if network.Status == nil || network.Status.Code == nil {
return network, ClientVpnNetworkAssociationStatusUnknown, nil
}

return network, aws.StringValue(network.Status.Code), nil
}
}

const (
ClientVpnRouteStatusNotFound = "NotFound"

Expand Down
50 changes: 50 additions & 0 deletions aws/internal/service/ec2/waiter/waiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,56 @@ func ClientVpnAuthorizationRuleRevoked(conn *ec2.EC2, authorizationRuleID string
return nil, err
}

const (
ClientVpnNetworkAssociationAssociatedTimeout = 10 * time.Minute

ClientVpnNetworkAssociationAssociatedDelay = 4 * time.Minute

ClientVpnNetworkAssociationDisassociatedTimeout = 10 * time.Minute

ClientVpnNetworkAssociationDisassociatedDelay = 4 * time.Minute

ClientVpnNetworkAssociationStatusPollInterval = 10 * time.Second
)

func ClientVpnNetworkAssociationAssociated(conn *ec2.EC2, networkAssociationID, clientVpnEndpointID string) (*ec2.TargetNetwork, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{ec2.AssociationStatusCodeAssociating},
Target: []string{ec2.AssociationStatusCodeAssociated},
Refresh: ClientVpnNetworkAssociationStatus(conn, networkAssociationID, clientVpnEndpointID),
Timeout: ClientVpnNetworkAssociationAssociatedTimeout,
Delay: ClientVpnNetworkAssociationAssociatedDelay,
PollInterval: ClientVpnNetworkAssociationStatusPollInterval,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*ec2.TargetNetwork); ok {
return output, err
}

return nil, err
}

func ClientVpnNetworkAssociationDisassociated(conn *ec2.EC2, networkAssociationID, clientVpnEndpointID string) (*ec2.TargetNetwork, error) {
stateConf := &resource.StateChangeConf{
Pending: []string{ec2.AssociationStatusCodeDisassociating},
Target: []string{},
Refresh: ClientVpnNetworkAssociationStatus(conn, networkAssociationID, clientVpnEndpointID),
Timeout: ClientVpnNetworkAssociationDisassociatedTimeout,
Delay: ClientVpnNetworkAssociationDisassociatedDelay,
PollInterval: ClientVpnNetworkAssociationStatusPollInterval,
}

outputRaw, err := stateConf.WaitForState()

if output, ok := outputRaw.(*ec2.TargetNetwork); ok {
return output, err
}

return nil, err
}

const (
ClientVpnRouteDeletedTimeout = 1 * time.Minute
)
Expand Down
4 changes: 2 additions & 2 deletions aws/resource_aws_ec2_client_vpn_authorization_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func testAccAwsEc2ClientVpnAuthorizationRule_basic(t *testing.T) {
var v ec2.AuthorizationRule
rStr := acctest.RandString(5)
resourceName := "aws_ec2_client_vpn_authorization_rule.test"
subnetResourceName := "aws_subnet.test"
subnetResourceName := "aws_subnet.test.0"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheckClientVPNSyncronize(t); testAccPreCheck(t) },
Expand Down Expand Up @@ -47,7 +47,7 @@ func testAccAwsEc2ClientVpnAuthorizationRule_groups(t *testing.T) {
rStr := acctest.RandString(5)
resource1Name := "aws_ec2_client_vpn_authorization_rule.test1"
resource2Name := "aws_ec2_client_vpn_authorization_rule.test2"
subnetResourceName := "aws_subnet.test"
subnetResourceName := "aws_subnet.test.0"

group1Name := "group_one"
group2Name := "group_two"
Expand Down
68 changes: 35 additions & 33 deletions aws/resource_aws_ec2_client_vpn_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
Expand All @@ -29,6 +30,7 @@ func init() {
F: testSweepEc2ClientVpnEndpoints,
Dependencies: []string{
"aws_directory_service_directory",
"aws_ec2_client_vpn_network_association",
},
})
}
Expand All @@ -41,37 +43,38 @@ func testSweepEc2ClientVpnEndpoints(region string) error {
}

conn := client.(*AWSClient).ec2conn
input := &ec2.DescribeClientVpnEndpointsInput{}

for {
output, err := conn.DescribeClientVpnEndpoints(input)

if testSweepSkipSweepError(err) {
log.Printf("[WARN] Skipping Client VPN Endpoint sweep for %s: %s", region, err)
return nil
}
var sweeperErrs *multierror.Error

if err != nil {
return fmt.Errorf("error retrieving Client VPN Endpoints: %w", err)
input := &ec2.DescribeClientVpnEndpointsInput{}
err = conn.DescribeClientVpnEndpointsPages(input, func(page *ec2.DescribeClientVpnEndpointsOutput, isLast bool) bool {
if page == nil {
return !isLast
}

for _, clientVpnEndpoint := range output.ClientVpnEndpoints {
for _, clientVpnEndpoint := range page.ClientVpnEndpoints {
id := aws.StringValue(clientVpnEndpoint.ClientVpnEndpointId)
log.Printf("[INFO] Deleting Client VPN Endpoint: %s", id)
log.Printf("[INFO] Deleting Client VPN endpoint: %s", id)
err := deleteClientVpnEndpoint(conn, id)
if err != nil {
return fmt.Errorf("error deleting Client VPN Endpoint (%s): %w", id, err)
sweeperErr := fmt.Errorf("error deleting Client VPN endpoint (%s): %w", id, err)
log.Printf("[ERROR] %s", sweeperErr)
sweeperErrs = multierror.Append(sweeperErrs, sweeperErr)
continue
}
}

if aws.StringValue(output.NextToken) == "" {
break
}

input.NextToken = output.NextToken
return !isLast
})
if testSweepSkipSweepError(err) {
log.Printf("[WARN] Skipping Client VPN endpoint sweep for %s: %s", region, err)
return sweeperErrs.ErrorOrNil() // In case we have completed some pages, but had errors
}
if err != nil {
sweeperErrs = multierror.Append(sweeperErrs, fmt.Errorf("error retrieving Client VPN endpoints: %w", err))
}

return nil
return sweeperErrs.ErrorOrNil()
}

// This is part of an experimental feature, do not use this as a starting point for tests
Expand All @@ -97,8 +100,9 @@ func TestAccAwsEc2ClientVpn_serial(t *testing.T) {
"disappears": testAccAwsEc2ClientVpnAuthorizationRule_disappears,
},
"NetworkAssociation": {
"basic": testAccAwsEc2ClientVpnNetworkAssociation_basic,
"disappears": testAccAwsEc2ClientVpnNetworkAssociation_disappears,
"basic": testAccAwsEc2ClientVpnNetworkAssociation_basic,
"disappears": testAccAwsEc2ClientVpnNetworkAssociation_disappears,
"securityGroups": testAccAwsEc2ClientVpnNetworkAssociation_securityGroups,
},
"Route": {
"basic": testAccAwsEc2ClientVpnRoute_basic,
Expand All @@ -107,6 +111,7 @@ func TestAccAwsEc2ClientVpn_serial(t *testing.T) {
},
}

t.Parallel()
for group, m := range testCases {
m := m
for name, tc := range m {
Expand Down Expand Up @@ -233,6 +238,8 @@ func testAccAwsEc2ClientVpnEndpoint_withLogGroup(t *testing.T) {
var v1, v2 ec2.ClientVpnEndpoint
rStr := acctest.RandString(5)
resourceName := "aws_ec2_client_vpn_endpoint.test"
logGroupResourceName := "aws_cloudwatch_log_group.lg"
logStreamResourceName := "aws_cloudwatch_log_stream.ls"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheckClientVPNSyncronize(t); testAccPreCheck(t) },
Expand All @@ -251,8 +258,8 @@ func testAccAwsEc2ClientVpnEndpoint_withLogGroup(t *testing.T) {
testAccCheckAwsEc2ClientVpnEndpointExists(resourceName, &v2),
resource.TestCheckResourceAttr(resourceName, "connection_log_options.#", "1"),
resource.TestCheckResourceAttr(resourceName, "connection_log_options.0.enabled", "true"),
resource.TestCheckResourceAttrSet(resourceName, "connection_log_options.0.cloudwatch_log_group"),
resource.TestCheckResourceAttrSet(resourceName, "connection_log_options.0.cloudwatch_log_stream"),
resource.TestCheckResourceAttrPair(resourceName, "connection_log_options.0.cloudwatch_log_group", logGroupResourceName, "name"),
resource.TestCheckResourceAttrPair(resourceName, "connection_log_options.0.cloudwatch_log_stream", logStreamResourceName, "name"),
),
},
{
Expand Down Expand Up @@ -445,16 +452,11 @@ resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "test1" {
vpc_id = aws_vpc.test.id
cidr_block = "10.0.1.0/24"
availability_zone = data.aws_availability_zones.available.names[0]
}

resource "aws_subnet" "test2" {
resource "aws_subnet" "test" {
count = 2
availability_zone = data.aws_availability_zones.available.names[count.index]
cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, count.index)
vpc_id = aws_vpc.test.id
cidr_block = "10.0.2.0/24"
availability_zone = data.aws_availability_zones.available.names[1]
}

resource "aws_directory_service_directory" "test" {
Expand All @@ -464,7 +466,7 @@ resource "aws_directory_service_directory" "test" {

vpc_settings {
vpc_id = aws_vpc.test.id
subnet_ids = [aws_subnet.test1.id, aws_subnet.test2.id]
subnet_ids = aws_subnet.test[*].id
}
}
`
Expand Down
Loading