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

r/aws_globalaccelerator_endpoint_group: Add aws_globalaccelerator_endpoint_group resource #8328

Merged

Conversation

john-delivuk
Copy link
Contributor

@john-delivuk john-delivuk commented Apr 16, 2019

Rebase of PR #7005

Partly addresses #6739

Changes proposed in this pull request:

  • New Resource: aws_globalaccelerator_endpoint_group

Output from acceptance testing:

$ make testacc TESTARGS='-run=TestAccAWSAvailabilityZones'

...

@ghost ghost added size/XL Managed by automation to categorize the size of a PR. provider Pertains to the provider itself, rather than any interaction with AWS. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure. labels Apr 16, 2019
@john-delivuk
Copy link
Contributor Author

I'll look at these build failure shortly. Sorry about that.

…vider-aws into f-globalaccelerator-endpoint-group
@john-delivuk john-delivuk force-pushed the f-globalaccelerator-endpoint-group branch from 476ba71 to b367746 Compare April 16, 2019 17:47
@john-delivuk
Copy link
Contributor Author

@bflad This is all ready to go. Let me know if I can do anything

@john-delivuk john-delivuk changed the title F globalaccelerator endpoint group r/aws_globalaccelerator_endpoint_group: Add aws_globalaccelerator_endpoint_group resource Apr 22, 2019
@john-delivuk
Copy link
Contributor Author

Anyway to get senpai to notice this?

@bflad bflad added new-resource Introduces a new resource. service/globalaccelerator Issues and PRs that pertain to the globalaccelerator service. labels May 15, 2019
Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

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

Hi @john-delivuk 👋 Thanks for rebasing the original pull request. See the below for some initial feedback items. Please reach out if you have any questions or do not have time to implement them.

aws/provider.go Show resolved Hide resolved
State: schema.ImportStatePassthrough,
},

Timeouts: &schema.ResourceTimeout{
Copy link
Contributor

Choose a reason for hiding this comment

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

These customizable timeouts seem extraneous as the timeout is not based on a scalable dimension (such as data size). I would suggest removing this schema declaration and replace d.Timeout(schema.TimeoutXXX) usage with the time duration. If operations take longer than the hardcoded defaults, we should increase them for everyone. 😄

},
"endpoint_group_region": {
Type: schema.TypeString,
Required: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

This attribute seems like it should default to the provider region rather than requiring configuration. 👍

Suggested change
Required: true,
Optional: true,
Computed: true,

In the code below:

region := meta.(*AWSClient).region
// ...
EndpointGroupRegion: aws.String(region),
// ...
if v, ok := d.GetOk("endpoint_group_region"); ok {
  opts.EndpointGroupRegion = aws.String(v.(string))
}

"health_check_interval_seconds": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

This attribute appears to have a default (which should be used for drift detection) and validation information in the Global Accelerator API Reference:

Suggested change
Computed: true,
Default: 30,
ValidateFunc: validation.IntBetween(10, 30),

"health_check_path": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

This attribute appears to have a default in the Global Accelerator API Reference, which should be used to perform drift detection:

Suggested change
Computed: true,
Default: "/",

Computed: true,
},
"endpoint_configurations": {
Type: schema.TypeList,
Copy link
Contributor

Choose a reason for hiding this comment

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

Does the API guarantee ordering of this attribute in its responses? If not, this should be switched to schema.TypeSet

return err
}

// Creating an endpoint group triggers the accelerator to change status to InPending
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic should reuse the available function (albeit slightly poor naming): resourceAwsGlobalAcceleratorAcceleratorWaitForState

err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)
if err != nil {
	return err
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this duplicate logic on merge.

return err
}

// Creating an endpoint group triggers the accelerator to change status to InPending
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic should reuse the available function (albeit slightly poor naming): resourceAwsGlobalAcceleratorAcceleratorWaitForState

err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)
if err != nil {
	return err
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this duplicate logic on merge.

return err
}

// Deleting an endpoint group triggers the accelerator to change status to InPending
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic should reuse the available function (albeit slightly poor naming): resourceAwsGlobalAcceleratorAcceleratorWaitForState

err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)
if err != nil {
	return err
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this duplicate logic on merge.

d.Set("health_check_protocol", endpointGroup.HealthCheckProtocol)
d.Set("threshold_count", endpointGroup.ThresholdCount)
d.Set("traffic_dial_percentage", endpointGroup.TrafficDialPercentage)
d.Set("endpoint_configurations", resourceAwsGlobalAcceleratorEndpointGroupFlattenEndpointDescriptions(endpointGroup.EndpointDescriptions))
Copy link
Contributor

Choose a reason for hiding this comment

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

When using d.Set() with aggregate types (TypeList, TypeSet, TypeMap), we should perform error checking to prevent issues where the code is not properly able to set the Terraform state. e.g.

Suggested change
d.Set("endpoint_configurations", resourceAwsGlobalAcceleratorEndpointGroupFlattenEndpointDescriptions(endpointGroup.EndpointDescriptions))
if err := d.Set("endpoint_configurations", resourceAwsGlobalAcceleratorEndpointGroupFlattenEndpointDescriptions(endpointGroup.EndpointDescriptions)); err != nil {
return fmt.Errorf("error setting endpoint_configurations: %s", err)
}

@john-delivuk
Copy link
Contributor Author

Hey @bflad Didn't expect this much feedback, just give me about 2 weeks and I'll put this together to the best of my ability.

@john-delivuk
Copy link
Contributor Author

I lied, I got most of this taken care of last night. I'll try to update the PR today.

@bflad bflad added the waiting-response Maintainers are waiting on response from community or contributor. label May 23, 2019
@ghost ghost added the documentation Introduces or discusses updates to documentation. label May 31, 2019
@john-delivuk
Copy link
Contributor Author

Sorry for the delay, please review the docs throughly, I went through this a few times, but I'm sure I overlooked something. Thanks @bflad

@ghost ghost removed the waiting-response Maintainers are waiting on response from community or contributor. label May 31, 2019
@MBali-GitHub
Copy link

Do we yet know by when this be released?

@bflad bflad self-assigned this Jun 19, 2019
Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

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

Hi @john-delivuk 👋 Thanks for the updates. I left some final review items below, but this is otherwise in pretty good shape. Please reach out if you have any questions or do not have time to implement the feedback.

website/aws.erb Outdated
@@ -1486,6 +1486,11 @@
<a href="/docs/providers/aws/r/globalaccelerator_accelerator.html">aws_globalaccelerator_accelerator</a>
</li>
</ul>
<ul class="nav">
<li>
<a href="/docs/providers/aws/r/globalaccelerator_endpoint_group.html">globalaccelerator_endpoint_group</a>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<a href="/docs/providers/aws/r/globalaccelerator_endpoint_group.html">globalaccelerator_endpoint_group</a>
<a href="/docs/providers/aws/r/globalaccelerator_endpoint_group.html">aws_globalaccelerator_endpoint_group</a>


acceleratorArn, err := resourceAwsGlobalAcceleratorListenerParseAcceleratorArn(d.Id())
if err != nil {
err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry if my original comment was unclear. This waiter should exist outside this error conditional and replace the duplicated StateChangeConf logic below. e.g.

acceleratorArn, err := resourceAwsGlobalAcceleratorListenerParseAcceleratorArn(d.Id())

if err != nil {
	return err
}

err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)

if err != nil {
	return err
}

return resourceAwsGlobalAcceleratorEndpointGroupRead(d, meta)

for i, configuration := range configurations {
m := make(map[string]interface{})

m["endpoint_id"] = *configuration.EndpointId
Copy link
Contributor

Choose a reason for hiding this comment

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

To prevent potential panics, this should use the AWS Go SDK provided conversion function:

Suggested change
m["endpoint_id"] = *configuration.EndpointId
m["endpoint_id"] = aws.StringValue(configuration.EndpointId)

m := make(map[string]interface{})

m["endpoint_id"] = *configuration.EndpointId
m["weight"] = *configuration.Weight
Copy link
Contributor

Choose a reason for hiding this comment

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

To prevent potential panics, this should use the AWS Go SDK provided conversion function:

Suggested change
m["weight"] = *configuration.Weight
m["weight"] = aws.Int64Value(configuration.Weight)


acceleratorArn, err := resourceAwsGlobalAcceleratorListenerParseAcceleratorArn(d.Id())
if err != nil {
err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here -- sorry if my original comment was unclear. This waiter should exist outside this error conditional and replace the duplicated StateChangeConf logic below. e.g.

acceleratorArn, err := resourceAwsGlobalAcceleratorListenerParseAcceleratorArn(d.Id())

if err != nil {
	return err
}

err = resourceAwsGlobalAcceleratorAcceleratorWaitForState(conn, acceleratorArn)

if err != nil {
	return err
}

return resourceAwsGlobalAcceleratorEndpointGroupRead(d, meta)


```hcl
resource "globalaccelerator_endpoint_group" "example" {
listener_arn = "arn:aws:globalaccelerator::123456789012:accelerator/1234abcd-abcd-1234-abcd-1234abcdefgh/listener/0123vxyz"
Copy link
Contributor

Choose a reason for hiding this comment

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

Examples should prefer to use resource references where possible to illustrate real world usage, e.g.

Suggested change
listener_arn = "arn:aws:globalaccelerator::123456789012:accelerator/1234abcd-abcd-1234-abcd-1234abcdefgh/listener/0123vxyz"
listener_arn = "${aws_globalaccelerator_listener.example.id}"

resource "globalaccelerator_endpoint_group" "example" {
listener_arn = "arn:aws:globalaccelerator::123456789012:accelerator/1234abcd-abcd-1234-abcd-1234abcdefgh/listener/0123vxyz"
endpoint_configuration {
EndpointId = "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188"
Copy link
Contributor

Choose a reason for hiding this comment

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

The argument name here is endpoint_id. Also, same here where examples should prefer to use resource references where possible to illustrate real world usage, e.g.

Suggested change
EndpointId = "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188"
endpoint_id = "${aws_lb.example.arn}"

listener_arn = "arn:aws:globalaccelerator::123456789012:accelerator/1234abcd-abcd-1234-abcd-1234abcdefgh/listener/0123vxyz"
endpoint_configuration {
EndpointId = "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188"
Weight = "100"
Copy link
Contributor

Choose a reason for hiding this comment

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

The argument name here is lowercase weight and is an integer which does not need to be wrapped in quotes:

Suggested change
Weight = "100"
weight = 100


**endpoint_configuration** supports the following attributes:

* `EndpointId` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* `EndpointId` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID.
* `endpoint_id` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID.

**endpoint_configuration** supports the following attributes:

* `EndpointId` - (Optional) An ID for the endpoint. If the endpoint is a Network Load Balancer or Application Load Balancer, this is the Amazon Resource Name (ARN) of the resource. If the endpoint is an Elastic IP address, this is the Elastic IP address allocation ID.
* `Weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* `Weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify.
* `weight` - (Optional) The weight associated with the endpoint. When you add weights to endpoints, you configure AWS Global Accelerator to route traffic based on proportions that you specify.

@bflad bflad added the waiting-response Maintainers are waiting on response from community or contributor. label Jun 19, 2019
@john-delivuk
Copy link
Contributor Author

@bflad Thanks for the feedback, everything is updated according to your notes. Let me know if there is anything else required.

@ghost ghost removed the waiting-response Maintainers are waiting on response from community or contributor. label Jun 19, 2019
@bflad bflad self-requested a review June 19, 2019 19:32
@bflad bflad added this to the v2.16.0 milestone Jun 19, 2019
@john-delivuk
Copy link
Contributor Author

For my own knowledge, should I mark resolved, or should I let the reviewer :)

Copy link
Contributor

@bflad bflad left a comment

Choose a reason for hiding this comment

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

Thanks for the updates, @john-delivuk. Performed some final adjustments in a followup commit to get the acceptance testing fully passing (noted below) and this is good to go. Great work. 🚀

Output from acceptance testing:

--- PASS: TestAccAwsGlobalAcceleratorEndpointGroup_basic (258.79s)
--- PASS: TestAccAwsGlobalAcceleratorEndpointGroup_update (316.32s)

"traffic_dial_percentage": {
Type: schema.TypeFloat,
Optional: true,
Default: 100,
Copy link
Contributor

Choose a reason for hiding this comment

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

When running the acceptance testing, this Default and ValidateFunc were causing the below failure:

--- FAIL: TestAccAwsGlobalAcceleratorEndpointGroup_basic (1.79s)
    testing.go:568: Step 0 error: config is invalid: expected type of traffic_dial_percentage to be int
--- FAIL: TestAccAwsGlobalAcceleratorEndpointGroup_update (1.79s)
    testing.go:568: Step 0 error: config is invalid: expected type of traffic_dial_percentage to be int

The fix here is to switch them to Default: 100.0 and ValidateFunc: validation.FloatBetween(0.0, 100.0) to match Type: schema.TypeFloat 👍

}

if v, ok := d.GetOk("endpoint_configuration"); ok {
opts.EndpointConfigurations = resourceAwsGlobalAcceleratorEndpointGroupExpandEndpointConfigurations(v.([]interface{}))
Copy link
Contributor

Choose a reason for hiding this comment

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

When running the acceptance testing, the type assertion here caused a panic:

panic: interface conversion: interface {} is *schema.Set, not []interface {}

goroutine 1169 [running]:
github.com/terraform-providers/terraform-provider-aws/aws.resourceAwsGlobalAcceleratorEndpointGroupCreate(0xc0013ed8f0, 0x5238f40, 0xc00008fc00, 0x2, 0xaa129c0)
	/Users/bflad/src/github.com/terraform-providers/terraform-provider-aws/aws/resource_aws_globalaccelerator_endpoint_group.go:136 +0xbb1

The fix here is to use v.(*schema.Set).List() for converting the Type: schema.TypeSet attribute into a []interface() for the function call. Same update needed in the Update function.

return err
}

// Creating an endpoint group triggers the accelerator to change status to InPending
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this duplicate logic on merge.

return err
}

// Creating an endpoint group triggers the accelerator to change status to InPending
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this duplicate logic on merge.

return err
}

// Deleting an endpoint group triggers the accelerator to change status to InPending
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing this duplicate logic on merge.

@@ -0,0 +1,55 @@
---
layout: "aws"
page_title: "AWS: globalaaws_globalaccelerator_endpoint_groupccelerator_endpoint_group"
Copy link
Contributor

Choose a reason for hiding this comment

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

Fixing on merge: page_title: "AWS: aws_globalaccelerator_endpoint_group"


Provides a Global Accelerator endpoint group.

## Attributes Reference
Copy link
Contributor

Choose a reason for hiding this comment

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

Fixing on merge.

resource.TestCheckResourceAttr(resourceName, "threshold_count", "3"),
resource.TestCheckResourceAttr(resourceName, "traffic_dial_percentage", "100"),
resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.#", "1"),
resource.TestCheckResourceAttr(resourceName, "endpoint_configuration.0.weight", "10"),
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the endpoint_configuration attribute is Type: schema.TypeSet, the .0. index in the state needs to instead be calculated from the Set function for the attribute (if Set is undefined for a TypeSet attribute, it falls back to an automatically calculated value from the underlying types):

--- FAIL: TestAccAwsGlobalAcceleratorEndpointGroup_basic (252.96s)
    testing.go:568: Step 0 error: Check failed: Check 9/9 error: aws_globalaccelerator_endpoint_group.example: Attribute 'endpoint_configuration.0.weight' not found

Since the endpoint_id value is dynamic, the index hash value in turn is dynamic as well and this type of state checking in the acceptance testing is problematic.

If the resource supports import, the ImportStateVerify: true testing will automatically ensures all state values match after Terraform refresh into an empty state (e.g. the values returned by just Read function itself), so this problematic TestCheckResourceAttr() can typically be removed fairly safely in that scenario.

Config: testAccGlobalAcceleratorEndpointGroup_update(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckGlobalAcceleratorEndpointGroupExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "health_check_interval_seconds", "10"),
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like the API needs at least one endpoint configuration for health check updates to actually occur (tried injecting a one minute delay between the update and read to no avail):

--- FAIL: TestAccAwsGlobalAcceleratorEndpointGroup_update (289.47s)
    testing.go:568: Step 1 error: Check failed: Check 2/8 error: aws_globalaccelerator_endpoint_group.example: Attribute 'health_check_interval_seconds' expected "10", got "30"

Opted to keep an endpoint configuration in the second configuration for now so the testing properly passes.

@bflad bflad merged commit 0dab14f into hashicorp:master Jun 20, 2019
pull bot pushed a commit to jamesrgregg/terraform-provider-aws that referenced this pull request Jun 20, 2019
 final feedback

Reference: hashicorp#8328

Output from acceptance testing:

```
--- PASS: TestAccAwsGlobalAcceleratorEndpointGroup_basic (258.79s)
--- PASS: TestAccAwsGlobalAcceleratorEndpointGroup_update (316.32s)
```
bflad added a commit that referenced this pull request Jun 20, 2019
@jorgebay
Copy link

Thanks @john-delivuk and @bflad for landing support for Global Accelerator!! 🎉

@bflad
Copy link
Contributor

bflad commented Jun 20, 2019

This has been released in version 2.16.0 of the Terraform AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

@ghost
Copy link

ghost commented Nov 3, 2019

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!

@ghost ghost locked and limited conversation to collaborators Nov 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
documentation Introduces or discusses updates to documentation. new-resource Introduces a new resource. provider Pertains to the provider itself, rather than any interaction with AWS. service/globalaccelerator Issues and PRs that pertain to the globalaccelerator service. size/XL Managed by automation to categorize the size of a PR. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants