-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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_dlm_lifecycle_policy #5558
New resource: aws_dlm_lifecycle_policy #5558
Conversation
Sorry I don't have time to give in depth review at the moment but to unblock you (hopefully) you can get a better handle on what's wrong with
At very quick glance of the flatten functions, here are a few hints:
As an example: func flattenDlmCreateRule(createRule *dlm.CreateRule) []map[string]interface{} {
if createRule == nil {
return []map[string]interface{}{}
}
result := make(map[string]interface{})
result["interval"] = aws.Int64Value(createRule.Interval)
result["internal_unit"] = aws.StringValue(createRule.IntervalUnit)
result["times"] = flattenStringList(createRule.Times)
return []map[string]interface{}{result}
} You can also help verify the resource read function by adding import support and using // in resource schema definition
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
}, // adding an acceptance testing TestStep
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
}, |
@bflad thanks for the pointers, think I've got it working now. I need to rerun the tests (not had a chance to run them since adding the import test) and then squash the mess of commits here. We also still need to wait for AWS to fix the API response as per the previously linked issue on the AWS SDK before this can be merged. |
// TODO: https://docs.aws.amazon.com/dlm/latest/APIReference/API_LifecyclePolicy.html#dlm-Type-LifecyclePolicy-Description says it has max length of 500 but doesn't mention the regex but SDK and CLI docs only mention the regex and not max length. Check this | ||
}, | ||
"execution_role_arn": { | ||
// TODO: Make this not required and if it's not provided then use the default service role, creating it if necessary |
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.
Does this want doing in first pass or should it be done later? I'm tempted to do the work for this if AWS take a long time fixing the API response which is blocking this.
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.
I think for starters that we can omit the handling in the code (so people can try this out) and document the solution on the website.
Any update on this? |
I'm still waiting for AWS to fix the response of the API. I've not checked again recently but the linked issue is still open so I'm leaving it until it's closed. After that I'll fix up the remaining TODOs on this PR and then it should be good for review. |
I've been really busy at work lately so not had any chance to come back and look at the review comments until now and no incentive to do so either with the DLM SDK/API response still being broken (chased AWS about it recently but it's still not fixed). I've just pushed fixes for all the feedback now and think it's good to go once the DLM API response is fixed (which should be announced in the linked issue or I can respond here when my support ticket is finally closed). When the DLM API response is fixed I'll rebase the branch to fix conflicts and squash the commits. I've implemented the |
Just got a reply from AWS support saying the DLM API fix is being deployed across all regions now and they'll let me know when it's fully rolled out. After that I'll test it without my patch to the SDK, rebase the branch to fix merge conflicts and squash the commits. |
@tomelliff let us know if you need anything! |
99ba014
to
e2cfcb8
Compare
e2cfcb8
to
28981d6
Compare
28981d6
to
3eb1360
Compare
Had a bit of a monster rebase there, let me know if I screwed anything up. Acceptance test output after rebase:
|
has this been merged? cant see it on the site |
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.
Fantastic work, @tomelliff! Thanks so much for working with AWS on the SDK issue. A few little minor things, but those were easy enough to quickly fix on merge so we can get this released today or tomorrow! 🚀
--- PASS: TestAccAWSDlmLifecyclePolicy_Basic (15.16s)
--- PASS: TestAccAWSDlmLifecyclePolicy_Full (20.28s)
log.Printf("[INFO] Creating DLM lifecycle policy: %s", input) | ||
out, err := conn.CreateLifecyclePolicy(&input) | ||
if err != nil { | ||
return 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.
Nit: We should return context about errors so operators and code maintainers can more easily troubleshoot issues, e.g.
return fmt.Errorf("error creating DLM Lifecycle Policy: %s", err)
Same with other similar messaging during Read/Update/Delete. 👍
PolicyId: aws.String(d.Id()), | ||
}) | ||
if err != nil { | ||
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" && !d.IsNewResource() { |
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.
Two things here:
- We have a helper for handling this type of logic, e.g.
isAWSErr(err, dlm.ErrCodeResourceNotFoundException, "")
- We should not create a special case during Read after Create that returns an error -- instead if this resource has eventual consistency issues, we should implement a
resource.Retry()
loop that retries for a minute or two (then can used.IsNewResource()
to determine if its a retryable error).
}) | ||
if err != nil { | ||
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" && !d.IsNewResource() { | ||
d.SetId("") |
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.
Nit: When triggering resource recreation, we should return a warning message in the logs so operators and code maintainers can more easily diagnose why it occurred, e.g.
log.Printf("[WARN] DLM Lifecycle Policy (%s) not found, removing from state", d.Id())
d.SetId("")
|
||
func expandDlmPolicyDetails(cfg []interface{}) *dlm.PolicyDetails { | ||
policyDetails := &dlm.PolicyDetails{} | ||
m := cfg[0].(map[string]interface{}) |
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.
To prevent potential panics, we should length and nil check the slice before accessing its first element, e.g.
if len(cfg) == 0 || cfg[0] == nil {
return nil
}
m := cfg[0].(map[string]interface{})
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.
Ack yeah, I keep missing these. Is there a linting rule or something we can use to check for this?
func flattenDlmTags(tags []*dlm.Tag) map[string]string { | ||
result := make(map[string]string) | ||
for _, t := range tags { | ||
result[*t.Key] = *t.Value |
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.
To prevent potential panics, we should prefer to use the SDK helpers in this case, e.g.
result[aws.StringValue(t.Key)] = aws.StringValue(t.Value)
return nil | ||
} | ||
|
||
func checkDlmLifecyclePolicyExists(name string) resource.TestCheckFunc { |
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 function should implement a similar (but opposite) check to the CheckDestroy, where it verifies that the expected resource does actually exist in the API. Admittedly, this is a little buried in the provider development documentation, here: https://www.terraform.io/docs/extend/testing/acceptance-tests/teststep.html#custom-check-functions
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
if rs.Primary.ID == "" {
return fmt.Errorf("Resource %s ID not found", name)
}
input := dlm.GetLifecyclePolicyInput{
PolicyId: aws.String(rs.Primary.ID),
}
out, err := conn.GetLifecyclePolicy(&input)
if err != nil {
return fmt.Errorf("error getting DLM Lifecycle Policy (%s): %s", rs.Primary.ID, err)
}
return nil
}
func TestAccAWSDlmLifecyclePolicyBasic(t *testing.T) { | ||
resourceName := "aws_dlm_lifecycle_policy.basic" | ||
|
||
resource.Test(t, resource.TestCase{ |
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.
Nit: This was written before resource.ParallelTest()
was available so we'll update these. 👍
func dlmLifecyclePolicyBasicConfig() string { | ||
return fmt.Sprint(` | ||
resource "aws_iam_role" "dlm_lifecycle_role" { | ||
name = "tf-acc-basic-dlm-lifecycle-role" |
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.
Nit: This would've been found with resource.ParallelTest()
(had it existed back then!), but resource names like these need to be randomized (check out other testing with rName
variables).
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_dlm_lifecycle_policy" | ||
sidebar_current: "docs-aws-resource-dlm-lifecycle-policy" |
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.
Merge note: Missing sidebar link in website/aws.erb
``` --- PASS: TestAccAWSDlmLifecyclePolicy_Basic (15.16s) --- PASS: TestAccAWSDlmLifecyclePolicy_Full (20.28s) ```
@bflad thanks for the review, fixes and merge :) This has been the largest PR I've raised for Terraform and I had a lot of issues with the (unnecessarily in some places IMO) deeply nested API of DLM. I don't get any other opportunities other than PRs to Terraform to write any Go so I learned a ton from this. |
This has been released in version 1.43.0 of the AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading. |
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! |
Fixes #5176
Changes proposed in this pull request:
Adds the
aws_dlm_lifecycle_policy
resourceOutput from acceptance testing:
This PR is currently WIP for a few reasons:
policy_details.0.schedule.0.create_rule.0.times
attribute in the basic test as AWS provides a value if you omit it but this doesn't end up back in the state currently. I'm not sure what I'm doing wrong here because there's nothing in the logs and no panics when refreshing state so would love a pointer here. The heavily nested structure of the API is much more complicated than other resources I've worked on so I guess I've ballsed something up here.I'll rebase the PR into a single commit after