-
Notifications
You must be signed in to change notification settings - Fork 242
Description
SDK version
HEAD
...
Relevant provider source code
{
cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("1"),
"b": cty.StringVal(""),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("1"),
"b": cty.NullVal(cty.String),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.NullVal(cty.String),
"b": cty.StringVal(""),
}),
}),
cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("1"),
"b": cty.StringVal(""),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal(""),
"b": cty.NullVal(cty.String),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.NullVal(cty.String),
"b": cty.NullVal(cty.String),
}),
}),
true,
},
...Terraform Configuration Files
resource "aws_wafv2_web_acl" "example" {
name = "example"
description = "Example WAF ACL"
scope = "CLOUDFRONT"
lifecycle {
ignore_changes = [
rule,
custom_response_body,
token_domains
]
}
default_action {
allow {}
}
visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "All"
sampled_requests_enabled = false
}
}Expected Behavior
Users attempting to apply a change to a aws_wafv2_web_acl with a very large number (>500) rules with ignore_changes on the rules should be able to apply quickly.
I'm looking to optimise ValuesSDKEquivalent trying to understand if the above test case should pass or not, it currently passes, but logically the sets are not equivalent.
Actual Behavior
The apply may take a very long time or never succeed or take a very long time, most of it spent in ValuesSDKEquivalent comparing all the rules.
Steps to Reproduce
terraform initterraform apply- Modify the resource outside of terraform using the AWS CLI or SDK to add a large number of rules (>500)
terraform plan- Notice length of plan time for no change- Modify description of
aws_wafv2_web_acl terraform plan- Notice length of plan time for single attribute changeterraform apply- Notice length of time before apply ever calls the AWS API to update the resource.
During both plan and apply a large amount of CPU and memory is consumed as well as taking an excessive amount of time to complete timing out in multi-hour CICD runs.
I would propose changing the loop in valuesSDKEquivalentSets to:
for ai, av := range as {
for bi, bv := range bs {
if beqs[bi] {
// continue on already matched items in `bs`
// this allows this `av` to match against later values in `bs` where an earlier `as` valus matched this `bv`
// this is a case where both sets contain two values each that are ValuesSDKEquivalent to each other
continue
}
if ValuesSDKEquivalent(av, bv) {
aeqs[ai] = true
beqs[bi] = true
// break on first match in `bs` against `av`
// this leaves any further matches in `bs` for later values in `as`
break
}
}This changes it such that
- items in
asare compared tobstill finding their first match. bsthat are already matched are skipped for comparison allowing laterasof 'equivalent' value are matched against later values inbs
This reduces the number of comparisons required significantly, but fails the above test case that is not currently in the unit tests.