-
Notifications
You must be signed in to change notification settings - Fork 241
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 init
terraform 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
as
are compared tobs
till finding their first match. bs
that are already matched are skipped for comparison allowing lateras
of '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.