-
Notifications
You must be signed in to change notification settings - Fork 9.2k
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
Add support for Client VPN Route resource #10508
Add support for Client VPN Route resource #10508
Conversation
2101378
to
f459858
Compare
ef30e87
to
cbad222
Compare
2632d4f
to
b8f0856
Compare
Minor fixes to schema and test config methods Adds tests and fixes bug in schema Change destination cidr block value in test config Change destination cidr block to internet access fix tab issue fix tab issue fix typo in Read Revert "tests/service/apigateway: Use internal implementation for TLS key/certificate" This reverts commit da4e688157425156683562803484924addf5e002. Fix test setup and add missing params Fix delete issue Fix gomft issues
b8f0856
to
7c964f3
Compare
@bflad Can you please review? |
Looks like this does the same as #10560 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @RickyRajinder, thanks for the PR. It's a great start for this feature. I've indicated a number of changes that can be made.
We'd also like to see some documentation added for the resource.
"origin": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
ForceNew: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ForceNew
does not work with Computed
fields
return fmt.Errorf("error creating client VPN route: %s", err) | ||
} | ||
|
||
d.SetId(resource.UniqueId()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should create a "synthetic id" which can be built out of the arguments that will uniquely identify this route. Something like < client_vpn_endpoint_id>_< target_vpc_subnet_id>_< destination_cidr_block>
. This is especially important since the resource is importable. The separator can be anything, but it should exclude any symbols that could be in the values, so in this case, avoid -
, .
, and /
.
The ID can then be unpacked to use in the Read
function to specify all of the parameters.
We use these in a number of resources, such as aws_route53_record
and aws_security_group_rule
.
func resourceAwsEc2ClientVpnRouteRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).ec2conn | ||
|
||
resp, err := conn.DescribeClientVpnRoutes(&ec2.DescribeClientVpnRoutesInput{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can add values for the Filters
field, to completely specify the route.
_, exists := d.GetOk("client_vpn_endpoint_id") | ||
if !exists { | ||
d.Set("client_vpn_endpoint_id", resp.Routes[0].ClientVpnEndpointId) | ||
} | ||
_, exists = d.GetOk("destination_cidr_block") | ||
if !exists { | ||
d.Set("destination_cidr_block", resp.Routes[0].DestinationCidr) | ||
} | ||
_, exists = d.GetOk("description") | ||
if !exists { | ||
d.Set("description", resp.Routes[0].Description) | ||
} | ||
_, exists = d.GetOk("target_vpc_subnet_id") | ||
if !exists { | ||
d.Set("target_vpc_subnet_id", resp.Routes[0].TargetSubnet) | ||
} | ||
_, exists = d.GetOk("origin") | ||
if !exists { | ||
d.Set("origin", resp.Routes[0].Origin) | ||
} | ||
_, exists = d.GetOk("status") | ||
if !exists { | ||
d.Set("status", resp.Routes[0].Status) | ||
} | ||
_, exists = d.GetOk("type") | ||
if !exists { | ||
d.Set("type", resp.Routes[0].Type) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should set all of the values, rather than checking for it being set. This way we ensure that the Terraform state contains the values as seen by AWS, and we can check for drift and update if needed.
} | ||
|
||
if err != nil { | ||
return fmt.Errorf("error reading client VPN route: %s", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're updating our error messages to use the Go 1.13 error wrapping verb %w
}, | ||
}) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some other tests that would be useful for this resource:
- Update the values on a route and ensure that the old one is deleted and the new one is created
- Have more than one route associated with the Client VPN to ensure that the
Read
function is getting the correct route- Also update one of the routes to make sure that only the correct route is updated
- Have a test for adding and then removing a route
- 0 -> 1 -> 0
- 1 -> 2 -> 1
}) | ||
|
||
for _, r := range resp.Routes { | ||
if *r.ClientVpnEndpointId == rs.Primary.Attributes["client_vpn_endpoint_id"] && !(*r.Status.Code == ec2.ClientVpnRouteStatusCodeDeleting) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should ensure that the route has been fully deleted, so ec2.ClientVpnRouteStatusCodeDeleting
should not be accepted for this check
|
||
conn := testAccProvider.Meta().(*AWSClient).ec2conn | ||
|
||
resp, err := conn.DescribeClientVpnRoutes(&ec2.DescribeClientVpnRoutesInput{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need to use the three required arguments to fully specify the correct route
target_vpc_subnet_id = "${aws_ec2_client_vpn_network_association.test.subnet_id}" | ||
description = "test client VPN route" | ||
} | ||
`, rName, rName, rName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since rName
is repeated here, you can use argument indexes, like %[1]s
} | ||
|
||
func testAccEc2ClientVpnRouteConfig(rName string) string { | ||
return testAccEc2ClientVpnRouteConfigAcmCertificateBase() + fmt.Sprintf(` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've added a function composeConfig()
that can be used to merge together configurations. E.g.
return composeConfig(
testAccEc2ClientVpnRouteConfigAcmCertificateBase(),
fmt.Sprint(`...`, rName))
As you add more tests, you can make a base configuration snippet that contains the common pieces, like the VPC and subnets
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks! |
Adds support for the following resource:
https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/cvpn-working-routes.html
Curently a workaround is implemented to access this API:
#7831 (comment)
Community Note
Closes #10437
Closes #7831
Release note for CHANGELOG:
Output from acceptance testing: