From 0bb166b2b718457ec15ffeef3c0cef8ccfc58a75 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:33:09 +0900 Subject: [PATCH 01/11] Implement regex_values for host_header, http_header, and path_pattern --- internal/service/elbv2/listener_rule.go | 162 +++++++++++++++++++----- 1 file changed, 129 insertions(+), 33 deletions(-) diff --git a/internal/service/elbv2/listener_rule.go b/internal/service/elbv2/listener_rule.go index 9f26aca54656..90353f73bd83 100644 --- a/internal/service/elbv2/listener_rule.go +++ b/internal/service/elbv2/listener_rule.go @@ -342,9 +342,17 @@ func resourceListenerRule() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "regex_values": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 128), + }, + }, names.AttrValues: { Type: schema.TypeSet, - Required: true, + Optional: true, MinItems: 1, Elem: &schema.Schema{ Type: schema.TypeString, @@ -365,13 +373,21 @@ func resourceListenerRule() *schema.Resource { Required: true, ValidateFunc: validation.StringMatch(regexache.MustCompile("^[0-9A-Za-z_!#$%&'*+,.^`|~-]{1,40}$"), ""), // was "," meant to be included? +-. creates a range including: +,-. }, + "regex_values": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 128), + }, + }, names.AttrValues: { Type: schema.TypeSet, Elem: &schema.Schema{ Type: schema.TypeString, ValidateFunc: validation.StringLenBetween(1, 128), }, - Required: true, + Optional: true, }, }, }, @@ -399,9 +415,17 @@ func resourceListenerRule() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "regex_values": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringLenBetween(1, 128), + }, + }, names.AttrValues: { Type: schema.TypeSet, - Required: true, + Optional: true, MinItems: 1, Elem: &schema.Schema{ Type: schema.TypeString, @@ -585,19 +609,10 @@ func resourceListenerRuleRead(ctx context.Context, d *schema.ResourceData, meta switch aws.ToString(condition.Field) { case "host-header": - conditionMap["host_header"] = []any{ - map[string]any{ - names.AttrValues: flex.FlattenStringValueSet(condition.HostHeaderConfig.Values), - }, - } + conditionMap["host_header"] = []any{flattenHostHeaderConditionConfig(condition.HostHeaderConfig)} case "http-header": - conditionMap["http_header"] = []any{ - map[string]any{ - "http_header_name": aws.ToString(condition.HttpHeaderConfig.HttpHeaderName), - names.AttrValues: flex.FlattenStringValueSet(condition.HttpHeaderConfig.Values), - }, - } + conditionMap["http_header"] = []any{flattenHttpHeaderConditionConfig(condition.HttpHeaderConfig)} case "http-request-method": conditionMap["http_request_method"] = []any{ @@ -607,11 +622,7 @@ func resourceListenerRuleRead(ctx context.Context, d *schema.ResourceData, meta } case "path-pattern": - conditionMap["path_pattern"] = []any{ - map[string]any{ - names.AttrValues: flex.FlattenStringValueSet(condition.PathPatternConfig.Values), - }, - } + conditionMap["path_pattern"] = []any{flattenPathPatternConditionConfig(condition.PathPatternConfig)} case "query-string": values := make([]any, len(condition.QueryStringConfig.Values)) @@ -860,23 +871,15 @@ func expandRuleConditions(tfList []any) ([]awstypes.RuleCondition, error) { if hostHeader, ok := tfMap["host_header"].([]any); ok && len(hostHeader) > 0 { field = "host-header" attrs += 1 - values := hostHeader[0].(map[string]any)[names.AttrValues].(*schema.Set) - apiObjects[i].HostHeaderConfig = &awstypes.HostHeaderConditionConfig{ - Values: flex.ExpandStringValueSet(values), - } + apiObjects[i].HostHeaderConfig = expandHostHeaderConditionConfig(hostHeader[0].(map[string]any)) } if httpHeader, ok := tfMap["http_header"].([]any); ok && len(httpHeader) > 0 { field = "http-header" attrs += 1 - httpHeaderMap := httpHeader[0].(map[string]any) - values := httpHeaderMap[names.AttrValues].(*schema.Set) - apiObjects[i].HttpHeaderConfig = &awstypes.HttpHeaderConditionConfig{ - HttpHeaderName: aws.String(httpHeaderMap["http_header_name"].(string)), - Values: flex.ExpandStringValueSet(values), - } + apiObjects[i].HttpHeaderConfig = expandHttpHeaderConditionConfig(httpHeader[0].(map[string]any)) } if httpRequestMethod, ok := tfMap["http_request_method"].([]any); ok && len(httpRequestMethod) > 0 { @@ -892,11 +895,8 @@ func expandRuleConditions(tfList []any) ([]awstypes.RuleCondition, error) { if pathPattern, ok := tfMap["path_pattern"].([]any); ok && len(pathPattern) > 0 { field = "path-pattern" attrs += 1 - values := pathPattern[0].(map[string]any)[names.AttrValues].(*schema.Set) - apiObjects[i].PathPatternConfig = &awstypes.PathPatternConditionConfig{ - Values: flex.ExpandStringValueSet(values), - } + apiObjects[i].PathPatternConfig = expandPathPatternConditionConfig(pathPattern[0].(map[string]any)) } if queryString, ok := tfMap["query_string"].(*schema.Set); ok && queryString.Len() > 0 { @@ -943,3 +943,99 @@ func expandRuleConditions(tfList []any) ([]awstypes.RuleCondition, error) { return apiObjects, nil } + +func expandHostHeaderConditionConfig(tfMap map[string]any) *awstypes.HostHeaderConditionConfig { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.HostHeaderConditionConfig{} + + if v, ok := tfMap[names.AttrValues].(*schema.Set); ok && v.Len() > 0 { + apiObject.Values = flex.ExpandStringValueSet(v) + } + if v, ok := tfMap["regex_values"].(*schema.Set); ok && v.Len() > 0 { + apiObject.RegexValues = flex.ExpandStringValueSet(v) + } + return apiObject +} + +func expandHttpHeaderConditionConfig(tfMap map[string]any) *awstypes.HttpHeaderConditionConfig { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.HttpHeaderConditionConfig{ + HttpHeaderName: aws.String(tfMap["http_header_name"].(string)), + } + + if v, ok := tfMap[names.AttrValues].(*schema.Set); ok && v.Len() > 0 { + apiObject.Values = flex.ExpandStringValueSet(v) + } + if v, ok := tfMap["regex_values"].(*schema.Set); ok && v.Len() > 0 { + apiObject.RegexValues = flex.ExpandStringValueSet(v) + } + return apiObject +} + +func expandPathPatternConditionConfig(tfMap map[string]any) *awstypes.PathPatternConditionConfig { + if tfMap == nil { + return nil + } + + apiObject := &awstypes.PathPatternConditionConfig{} + if v, ok := tfMap[names.AttrValues].(*schema.Set); ok && v.Len() > 0 { + apiObject.Values = flex.ExpandStringValueSet(v) + } + if v, ok := tfMap["regex_values"].(*schema.Set); ok && v.Len() > 0 { + apiObject.RegexValues = flex.ExpandStringValueSet(v) + } + return apiObject +} + +func flattenHostHeaderConditionConfig(apiObject *awstypes.HostHeaderConditionConfig) map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{} + if apiObject.Values != nil { + tfMap[names.AttrValues] = flex.FlattenStringValueSet(apiObject.Values) + } + if apiObject.RegexValues != nil { + tfMap["regex_values"] = flex.FlattenStringValueSet(apiObject.RegexValues) + } + + return tfMap +} + +func flattenHttpHeaderConditionConfig(apiObject *awstypes.HttpHeaderConditionConfig) map[string]any { + if apiObject == nil { + return nil + } + tfMap := map[string]any{ + "http_header_name": aws.ToString(apiObject.HttpHeaderName), + } + if apiObject.Values != nil { + tfMap[names.AttrValues] = flex.FlattenStringValueSet(apiObject.Values) + } + if apiObject.RegexValues != nil { + tfMap["regex_values"] = flex.FlattenStringValueSet(apiObject.RegexValues) + } + return tfMap +} + +func flattenPathPatternConditionConfig(apiObject *awstypes.PathPatternConditionConfig) map[string]any { + if apiObject == nil { + return nil + } + + tfMap := map[string]any{} + if apiObject.Values != nil { + tfMap[names.AttrValues] = flex.FlattenStringValueSet(apiObject.Values) + } + if apiObject.RegexValues != nil { + tfMap["regex_values"] = flex.FlattenStringValueSet(apiObject.RegexValues) + } + return tfMap +} From db021ca452f57d1dff07df94fd195da99a66a2f0 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:34:44 +0900 Subject: [PATCH 02/11] Add an acctest for regex_values --- internal/service/elbv2/listener_rule_test.go | 172 ++++++++++++++++++- 1 file changed, 165 insertions(+), 7 deletions(-) diff --git a/internal/service/elbv2/listener_rule_test.go b/internal/service/elbv2/listener_rule_test.go index 38181652614f..76cbe995e26c 100644 --- a/internal/service/elbv2/listener_rule_test.go +++ b/internal/service/elbv2/listener_rule_test.go @@ -1571,13 +1571,14 @@ func TestAccELBV2ListenerRule_conditionHostHeader(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "action.#", "1"), resource.TestCheckResourceAttr(resourceName, "condition.#", "1"), resource.TestCheckTypeSetElemNestedAttrs(resourceName, "condition.*", map[string]string{ - "host_header.#": "1", - "host_header.0.values.#": "2", - "http_header.#": "0", - "http_request_method.#": "0", - "path_pattern.#": "0", - "query_string.#": "0", - "source_ip.#": "0", + "host_header.#": "1", + "host_header.0.values.#": "2", + "host_header.0.regex_values.#": "0", + "http_header.#": "0", + "http_request_method.#": "0", + "path_pattern.#": "0", + "query_string.#": "0", + "source_ip.#": "0", }), resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.host_header.0.values.*", "example.com"), resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.host_header.0.values.*", "www.example.com"), @@ -1587,6 +1588,47 @@ func TestAccELBV2ListenerRule_conditionHostHeader(t *testing.T) { }) } +func TestAccELBV2ListenerRule_conditionHostHeaderRegex(t *testing.T) { + ctx := acctest.Context(t) + var conf awstypes.Rule + lbName := fmt.Sprintf("testrule-hostHeader-%s", sdkacctest.RandString(12)) + + resourceName := "aws_lb_listener_rule.static" + frontEndListenerResourceName := "aws_lb_listener.front_end" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckListenerRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccListenerRuleConfig_conditionHostHeaderRegex(lbName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckListenerRuleExists(ctx, resourceName, &conf), + acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf(`listener-rule/app/%s/.+$`, lbName))), + resource.TestCheckResourceAttrPair(resourceName, "listener_arn", frontEndListenerResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrPriority, "100"), + resource.TestCheckResourceAttr(resourceName, "action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "condition.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "condition.*", map[string]string{ + "host_header.#": "1", + "host_header.0.values.#": "0", + "host_header.0.regex_values.#": "2", + "http_header.#": "0", + "http_request_method.#": "0", + "path_pattern.#": "0", + "query_string.#": "0", + "source_ip.#": "0", + }), + resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.host_header.0.regex_values.*", "^example\\.com$"), + resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.host_header.0.regex_values.*", "^www[0-9]+\\.example\\.com$"), + ), + }, + }, + }) +} + func TestAccELBV2ListenerRule_conditionHTTPHeader(t *testing.T) { ctx := acctest.Context(t) var conf awstypes.Rule @@ -1615,6 +1657,7 @@ func TestAccELBV2ListenerRule_conditionHTTPHeader(t *testing.T) { "http_header.#": "1", "http_header.0.http_header_name": "X-Forwarded-For", "http_header.0.values.#": "2", + "http_header.0.regex_values.#": "0", "http_request_method.#": "0", "path_pattern.#": "0", "query_string.#": "0", @@ -1627,6 +1670,7 @@ func TestAccELBV2ListenerRule_conditionHTTPHeader(t *testing.T) { "http_header.#": "1", "http_header.0.http_header_name": "Zz9~|_^.-+*'&%$#!0aA", "http_header.0.values.#": "1", + "http_header.0.regex_values.#": "0", "http_request_method.#": "0", "path_pattern.#": "0", "query_string.#": "0", @@ -1639,6 +1683,48 @@ func TestAccELBV2ListenerRule_conditionHTTPHeader(t *testing.T) { }) } +func TestAccELBV2ListenerRule_conditionHTTPHeaderRegex(t *testing.T) { + ctx := acctest.Context(t) + var conf awstypes.Rule + lbName := fmt.Sprintf("testrule-httpHeader-%s", sdkacctest.RandString(12)) + + resourceName := "aws_lb_listener_rule.static" + frontEndListenerResourceName := "aws_lb_listener.front_end" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckListenerRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccListenerRuleConfig_conditionHTTPHeaderRegex(lbName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckListenerRuleExists(ctx, resourceName, &conf), + acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf(`listener-rule/app/%s/.+$`, lbName))), + resource.TestCheckResourceAttrPair(resourceName, "listener_arn", frontEndListenerResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrPriority, "100"), + resource.TestCheckResourceAttr(resourceName, "action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "condition.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "condition.*", map[string]string{ + "host_header.#": "0", + "http_header.#": "1", + "http_header.0.http_header_name": "User-Agent", + "http_header.0.values.#": "0", + "http_header.0.regex_values.#": "2", + "http_request_method.#": "0", + "path_pattern.#": "0", + "query_string.#": "0", + "source_ip.#": "0", + }), + resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.http_header.0.regex_values.*", "A.+"), + resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.http_header.0.regex_values.*", "B.*C"), + ), + }, + }, + }) +} + func TestAccELBV2ListenerRule_ConditionHTTPHeader_invalid(t *testing.T) { ctx := acctest.Context(t) resource.ParallelTest(t, resource.TestCase{ @@ -1735,6 +1821,47 @@ func TestAccELBV2ListenerRule_conditionPathPattern(t *testing.T) { }) } +func TestAccELBV2ListenerRule_conditionPathPatternRegex(t *testing.T) { + ctx := acctest.Context(t) + var conf awstypes.Rule + lbName := fmt.Sprintf("testrule-pathPattern-%s", sdkacctest.RandString(11)) + + resourceName := "aws_lb_listener_rule.static" + frontEndListenerResourceName := "aws_lb_listener.front_end" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckListenerRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccListenerRuleConfig_conditionPathPatternRegex(lbName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckListenerRuleExists(ctx, resourceName, &conf), + acctest.MatchResourceAttrRegionalARN(ctx, resourceName, names.AttrARN, "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf(`listener-rule/app/%s/.+$`, lbName))), + resource.TestCheckResourceAttrPair(resourceName, "listener_arn", frontEndListenerResourceName, names.AttrARN), + resource.TestCheckResourceAttr(resourceName, names.AttrPriority, "100"), + resource.TestCheckResourceAttr(resourceName, "action.#", "1"), + resource.TestCheckResourceAttr(resourceName, "condition.#", "1"), + resource.TestCheckTypeSetElemNestedAttrs(resourceName, "condition.*", map[string]string{ + "host_header.#": "0", + "http_header.#": "0", + "http_request_method.#": "0", + "path_pattern.#": "1", + "path_pattern.0.values.#": "0", + "path_pattern.0.regex_values.#": "2", + "query_string.#": "0", + "source_ip.#": "0", + }), + resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.path_pattern.0.regex_values.*", "^\\/api\\/(.*)$"), + resource.TestCheckTypeSetElemAttr(resourceName, "condition.*.path_pattern.0.regex_values.*", "^\\/api2\\/(.*)$"), + ), + }, + }, + }) +} + func TestAccELBV2ListenerRule_conditionQueryString(t *testing.T) { ctx := acctest.Context(t) var conf awstypes.Rule @@ -4500,6 +4627,16 @@ condition { `, lbName) } +func testAccListenerRuleConfig_conditionHostHeaderRegex(lbName string) string { + return testAccListenerRuleConfig_conditionBase(` +condition { + host_header { + regex_values = ["^example\\.com$", "^www[0-9]+\\.example\\.com$"] + } +} +`, lbName) +} + func testAccListenerRuleConfig_conditionHTTPHeader(lbName string) string { return testAccListenerRuleConfig_conditionBase(` condition { @@ -4518,6 +4655,17 @@ condition { `, lbName) } +func testAccListenerRuleConfig_conditionHTTPHeaderRegex(lbName string) string { + return testAccListenerRuleConfig_conditionBase(` +condition { + http_header { + http_header_name = "User-Agent" + regex_values = ["A.+", "B.*C"] + } +} +`, lbName) +} + func testAccListenerRuleConfig_conditionHTTPHeaderInvalid() string { return ` data "aws_partition" "current" {} @@ -4568,6 +4716,16 @@ condition { `, lbName) } +func testAccListenerRuleConfig_conditionPathPatternRegex(lbName string) string { + return testAccListenerRuleConfig_conditionBase(` +condition { + path_pattern { + regex_values = ["^\\/api\\/(.*)$", "^\\/api2\\/(.*)$"] + } +} +`, lbName) +} + func testAccListenerRuleConfig_conditionQueryString(lbName string) string { return testAccListenerRuleConfig_conditionBase(` condition { From b92cb47a60248e2d3d313824339be9758cfe8d2a Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:35:10 +0900 Subject: [PATCH 03/11] Update the resource documentation to include regex_values --- website/docs/r/lb_listener_rule.html.markdown | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/website/docs/r/lb_listener_rule.html.markdown b/website/docs/r/lb_listener_rule.html.markdown index 34d996f0eae0..32e00e288f95 100644 --- a/website/docs/r/lb_listener_rule.html.markdown +++ b/website/docs/r/lb_listener_rule.html.markdown @@ -304,21 +304,34 @@ One or more condition blocks can be set per rule. Most condition types can only Condition Blocks (for `condition`) support the following: -* `host_header` - (Optional) Contains a single `values` item which is a list of host header patterns to match. The maximum size of each pattern is 128 characters. Comparison is case insensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). Only one pattern needs to match for the condition to be satisfied. +* `host_header` - (Optional) Host header patterns to match. [Host Header block](#host-header-blocks) fields documented below. * `http_header` - (Optional) HTTP headers to match. [HTTP Header block](#http-header-blocks) fields documented below. * `http_request_method` - (Optional) Contains a single `values` item which is a list of HTTP request methods or verbs to match. Maximum size is 40 characters. Only allowed characters are A-Z, hyphen (-) and underscore (\_). Comparison is case sensitive. Wildcards are not supported. Only one needs to match for the condition to be satisfied. AWS recommends that GET and HEAD requests are routed in the same way because the response to a HEAD request may be cached. -* `path_pattern` - (Optional) Contains a single `values` item which is a list of path patterns to match against the request URL. Maximum size of each pattern is 128 characters. Comparison is case sensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). Only one pattern needs to match for the condition to be satisfied. Path pattern is compared only to the path of the URL, not to its query string. To compare against the query string, use a `query_string` condition. +* `path_pattern` - (Optional) Path patterns to match against the request URL. [Path Pattern block](#path-pattern-blocks) fields documented below. * `query_string` - (Optional) Query strings to match. [Query String block](#query-string-blocks) fields documented below. * `source_ip` - (Optional) Contains a single `values` item which is a list of source IP CIDR notations to match. You can use both IPv4 and IPv6 addresses. Wildcards are not supported. Condition is satisfied if the source IP address of the request matches one of the CIDR blocks. Condition is not satisfied by the addresses in the `X-Forwarded-For` header, use `http_header` condition instead. ~> **NOTE::** Exactly one of `host_header`, `http_header`, `http_request_method`, `path_pattern`, `query_string` or `source_ip` must be set per condition. +#### Host Header Blocks + +Host Header Blocks (for `host_header`) support the following: + +* `regex_values` - (Optional) List of regular expressions to compare against the host header. The maximum length of each string is 128 characters. Conflicts with `values`. +* `values` - (Optional) List of host header value patterns to match. Maximum size of each pattern is 128 characters. Comparison is case-insensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). Only one pattern needs to match for the condition to be satisfied. Conflicts with `regex_values`. + #### HTTP Header Blocks HTTP Header Blocks (for `http_header`) support the following: -* `http_header_name` - (Required) Name of HTTP header to search. The maximum size is 40 characters. Comparison is case insensitive. Only RFC7240 characters are supported. Wildcards are not supported. You cannot use HTTP header condition to specify the host header, use a `host-header` condition instead. -* `values` - (Required) List of header value patterns to match. Maximum size of each pattern is 128 characters. Comparison is case insensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). If the same header appears multiple times in the request they will be searched in order until a match is found. Only one pattern needs to match for the condition to be satisfied. To require that all of the strings are a match, create one condition block per string. +* `http_header_name` - (Required) Name of HTTP header to search. The maximum size is 40 characters. Comparison is case-insensitive. Only RFC7240 characters are supported. Wildcards are not supported. You cannot use HTTP header condition to specify the host header, use a `host-header` condition instead. +* `regex_values` - (Optional) List of regular expression to compare against the HTTP header. The maximum length of each string is 128 characters. Conflicts with `values`. +* `values` - (Optional) List of header value patterns to match. Maximum size of each pattern is 128 characters. Comparison is case-insensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). If the same header appears multiple times in the request they will be searched in order until a match is found. Only one pattern needs to match for the condition to be satisfied. To require that all of the strings are a match, create one condition block per string. Conflicts with `regex_values`. + +#### Path Pattern Blocks + +* `regex_values` - (Optional) List of regular expressions to compare against the request URL. The maximum length of each string is 128 characters. Conflicts with `values`. +* `values` - (Optional) List of path patterns to compare against the request URL. Maximum size of each pattern is 128 characters. Comparison is case-sensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). Only one pattern needs to match for the condition to be satisfied. Path pattern is compared only to the path of the URL, not to its query string. To compare against the query string, use a `query_string` condition. Conflicts with `regex_values`. #### Query String Blocks From 7858040db7d9034835eb0cd77f241b7b1d96325a Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:35:56 +0900 Subject: [PATCH 04/11] Implement regex_values for the data source --- .../elbv2/listener_rule_data_source.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/internal/service/elbv2/listener_rule_data_source.go b/internal/service/elbv2/listener_rule_data_source.go index d68a9d06389d..3974d4a46411 100644 --- a/internal/service/elbv2/listener_rule_data_source.go +++ b/internal/service/elbv2/listener_rule_data_source.go @@ -224,6 +224,10 @@ func (d *listenerRuleDataSource) Schema(ctx context.Context, req datasource.Sche CustomType: fwtypes.NewListNestedObjectTypeOf[hostHeaderConfigModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ + "regex_values": schema.SetAttribute{ + ElementType: types.StringType, + Computed: true, + }, names.AttrValues: schema.SetAttribute{ ElementType: types.StringType, Computed: true, @@ -238,6 +242,10 @@ func (d *listenerRuleDataSource) Schema(ctx context.Context, req datasource.Sche "http_header_name": schema.StringAttribute{ Computed: true, }, + "regex_values": schema.SetAttribute{ + ElementType: types.StringType, + Computed: true, + }, names.AttrValues: schema.SetAttribute{ ElementType: types.StringType, Computed: true, @@ -260,6 +268,10 @@ func (d *listenerRuleDataSource) Schema(ctx context.Context, req datasource.Sche CustomType: fwtypes.NewListNestedObjectTypeOf[pathPatternConfigModel](ctx), NestedObject: schema.NestedBlockObject{ Attributes: map[string]schema.Attribute{ + "regex_values": schema.SetAttribute{ + ElementType: types.StringType, + Computed: true, + }, names.AttrValues: schema.SetAttribute{ ElementType: types.StringType, Computed: true, @@ -464,11 +476,13 @@ type ruleConditionModel struct { } type hostHeaderConfigModel struct { - Values fwtypes.SetValueOf[types.String] `tfsdk:"values"` + RegexValues fwtypes.SetValueOf[types.String] `tfsdk:"regex_values"` + Values fwtypes.SetValueOf[types.String] `tfsdk:"values"` } type httpHeaderConfigModel struct { HTTPHeaderName types.String `tfsdk:"http_header_name"` + RegexValues fwtypes.SetValueOf[types.String] `tfsdk:"regex_values"` Values fwtypes.SetValueOf[types.String] `tfsdk:"values"` } @@ -477,7 +491,8 @@ type httpRquestMethodConfigModel struct { } type pathPatternConfigModel struct { - Values fwtypes.SetValueOf[types.String] `tfsdk:"values"` + RegexValues fwtypes.SetValueOf[types.String] `tfsdk:"regex_values"` + Values fwtypes.SetValueOf[types.String] `tfsdk:"values"` } type queryStringConfigModel struct { From 68acfc6c1f19cb30e411de7e93f5c34fdb52d0f0 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:36:17 +0900 Subject: [PATCH 05/11] Add an acctest for regex_values in the data source --- .../elbv2/listener_rule_data_source_test.go | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/internal/service/elbv2/listener_rule_data_source_test.go b/internal/service/elbv2/listener_rule_data_source_test.go index c4e3152f9d65..ca0d0d067fb3 100644 --- a/internal/service/elbv2/listener_rule_data_source_test.go +++ b/internal/service/elbv2/listener_rule_data_source_test.go @@ -588,6 +588,7 @@ func TestAccELBV2ListenerRuleDataSource_conditionHostHeader(t *testing.T) { statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ expectKnownCondition("host_header", knownvalue.ListExact([]knownvalue.Check{ knownvalue.ObjectExact(map[string]knownvalue.Check{ + "regex_values": knownvalue.Null(), names.AttrValues: knownvalue.SetExact([]knownvalue.Check{ knownvalue.StringExact("example.com"), knownvalue.StringExact("www.example.com"), @@ -601,6 +602,45 @@ func TestAccELBV2ListenerRuleDataSource_conditionHostHeader(t *testing.T) { }) } +func TestAccELBV2ListenerRuleDataSource_conditionHostHeaderRegex(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var listenerRule awstypes.Rule + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_lb_listener_rule.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckListenerRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccListenerRuleDataSourceConfig_conditionHostHeaderRegex(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckListenerRuleExists(ctx, dataSourceName, &listenerRule), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ + expectKnownCondition("host_header", knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "regex_values": knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("^example\\.com$"), + knownvalue.StringExact("^www[0-9]+\\.example\\.com$"), + }), + names.AttrValues: knownvalue.Null(), + }), + })), + })), + }, + }, + }, + }) +} + func TestAccELBV2ListenerRuleDataSource_conditionHTTPHeader(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -627,6 +667,7 @@ func TestAccELBV2ListenerRuleDataSource_conditionHTTPHeader(t *testing.T) { expectKnownCondition("http_header", knownvalue.ListExact([]knownvalue.Check{ knownvalue.ObjectExact(map[string]knownvalue.Check{ "http_header_name": knownvalue.StringExact("X-Forwarded-For"), + "regex_values": knownvalue.Null(), names.AttrValues: knownvalue.SetExact([]knownvalue.Check{ knownvalue.StringExact("192.168.1.*"), knownvalue.StringExact("10.0.0.*"), @@ -640,6 +681,46 @@ func TestAccELBV2ListenerRuleDataSource_conditionHTTPHeader(t *testing.T) { }) } +func TestAccELBV2ListenerRuleDataSource_conditionHTTPHeaderRegex(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var listenerRule awstypes.Rule + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_lb_listener_rule.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckListenerRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccListenerRuleDataSourceConfig_conditionHTTPHeaderRegex(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckListenerRuleExists(ctx, dataSourceName, &listenerRule), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ + expectKnownCondition("http_header", knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "http_header_name": knownvalue.StringExact("User-Agent"), + "regex_values": knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("A.+"), + knownvalue.StringExact("B.*C"), + }), + names.AttrValues: knownvalue.Null(), + }), + })), + })), + }, + }, + }, + }) +} + func TestAccELBV2ListenerRuleDataSource_conditionHTTPRequestMethod(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -703,6 +784,7 @@ func TestAccELBV2ListenerRuleDataSource_conditionPathPattern(t *testing.T) { statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ expectKnownCondition("path_pattern", knownvalue.ListExact([]knownvalue.Check{ knownvalue.ObjectExact(map[string]knownvalue.Check{ + "regex_values": knownvalue.Null(), names.AttrValues: knownvalue.SetExact([]knownvalue.Check{ knownvalue.StringExact("/public/*"), knownvalue.StringExact("/cgi-bin/*"), @@ -716,6 +798,45 @@ func TestAccELBV2ListenerRuleDataSource_conditionPathPattern(t *testing.T) { }) } +func TestAccELBV2ListenerRuleDataSource_conditionPathPatternRegex(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var listenerRule awstypes.Rule + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_lb_listener_rule.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ELBV2ServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckListenerRuleDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccListenerRuleDataSourceConfig_conditionPathPatternRegex(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckListenerRuleExists(ctx, dataSourceName, &listenerRule), + ), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ + expectKnownCondition("path_pattern", knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "regex_values": knownvalue.SetExact([]knownvalue.Check{ + knownvalue.StringExact("^\\/api\\/(.*)$"), + knownvalue.StringExact("^\\/api2\\/(.*)$"), + }), + names.AttrValues: knownvalue.Null(), + }), + })), + })), + }, + }, + }, + }) +} + func TestAccELBV2ListenerRuleDataSource_conditionQueryString(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -1184,6 +1305,30 @@ resource "aws_lb_listener_rule" "test" { `) } +func testAccListenerRuleDataSourceConfig_conditionHostHeaderRegex(rName string) string { + return acctest.ConfigCompose(testAccListenerRuleConfig_baseWithHTTPListener(rName), ` +data "aws_lb_listener_rule" "test" { + arn = aws_lb_listener_rule.test.arn +} + +resource "aws_lb_listener_rule" "test" { + listener_arn = aws_lb_listener.test.arn + priority = 100 + + action { + type = "forward" + target_group_arn = aws_lb_target_group.test.arn + } + + condition { + host_header { + regex_values = ["^example\\.com$", "^www[0-9]+\\.example\\.com$"] + } + } +} +`) +} + func testAccListenerRuleDataSourceConfig_conditionHTTPHeader(rName string) string { return acctest.ConfigCompose(testAccListenerRuleConfig_baseWithHTTPListener(rName), ` data "aws_lb_listener_rule" "test" { @@ -1209,6 +1354,31 @@ resource "aws_lb_listener_rule" "test" { `) } +func testAccListenerRuleDataSourceConfig_conditionHTTPHeaderRegex(rName string) string { + return acctest.ConfigCompose(testAccListenerRuleConfig_baseWithHTTPListener(rName), ` +data "aws_lb_listener_rule" "test" { + arn = aws_lb_listener_rule.test.arn +} + +resource "aws_lb_listener_rule" "test" { + listener_arn = aws_lb_listener.test.arn + priority = 100 + + action { + type = "forward" + target_group_arn = aws_lb_target_group.test.arn + } + + condition { + http_header { + http_header_name = "User-Agent" + regex_values = ["A.+", "B.*C"] + } + } +} +`) +} + func testAccListenerRuleDataSourceConfig_conditionHTTPRequestMethod(rName string) string { return acctest.ConfigCompose(testAccListenerRuleConfig_baseWithHTTPListener(rName), ` data "aws_lb_listener_rule" "test" { @@ -1257,6 +1427,30 @@ resource "aws_lb_listener_rule" "test" { `) } +func testAccListenerRuleDataSourceConfig_conditionPathPatternRegex(rName string) string { + return acctest.ConfigCompose(testAccListenerRuleConfig_baseWithHTTPListener(rName), ` +data "aws_lb_listener_rule" "test" { + arn = aws_lb_listener_rule.test.arn +} + +resource "aws_lb_listener_rule" "test" { + listener_arn = aws_lb_listener.test.arn + priority = 100 + + action { + type = "forward" + target_group_arn = aws_lb_target_group.test.arn + } + + condition { + path_pattern { + regex_values = ["^\\/api\\/(.*)$", "^\\/api2\\/(.*)$"] + } + } +} +`) +} + func testAccListenerRuleDataSourceConfig_conditionQueryString(rName string) string { return acctest.ConfigCompose(testAccListenerRuleConfig_baseWithHTTPListener(rName), ` data "aws_lb_listener_rule" "test" { From 03b3507b6c938fc4568234346c30e7928e4ac177 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:37:08 +0900 Subject: [PATCH 06/11] Update the data source documentation to include regex_values --- website/docs/d/lb_listener_rule.html.markdown | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/website/docs/d/lb_listener_rule.html.markdown b/website/docs/d/lb_listener_rule.html.markdown index cebd3c359abf..7c4428da4c8b 100644 --- a/website/docs/d/lb_listener_rule.html.markdown +++ b/website/docs/d/lb_listener_rule.html.markdown @@ -143,20 +143,33 @@ This data source exports the following attributes in addition to the arguments a ### `condition` -* `host_header` - Contains a single attribute `values`, which contains a set of host names. +* `host_header` - Host header patterns to match. + [Detailed below](#host_header). * `http_header` - HTTP header and values to match. [Detailed below](#http_header). * `http_request_method` - Contains a single attribute `values`, which contains a set of HTTP request methods. -* `path_pattern` - Contains a single attribute `values`, which contains a set of path patterns to compare against the request URL. +* `path_pattern` - Path patterns to compare against the request URL. + [Detailed below](#path_pattern). * `query_string` - Query string parameters to match. [Detailed below](#query_string). * `source_ip` - Contains a single attribute `values`, which contains a set of source IPs in CIDR notation. +#### `host_header` + +* `regex_values` - Set of regular expressions to compare against the host header. +* `values` - Set of host header value patterns to match. + #### `http_header` * `http_header_name` - Name of the HTTP header to match. +* `regex_values` - Set of regular expression to compare against the HTTP header. * `values` - Set of values to compare against the value of the HTTP header. +#### `path_pattern` + +* `regex_values` - Set of regular expressions to compare against the request URL. +* `values` - Set of path patterns to compare against the request URL. + #### `query_string` * `values` - Set of `key`-`value` pairs indicating the query string parameters to match. From 16e964759288550793aad661c5c532b89453f606 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:57:20 +0900 Subject: [PATCH 07/11] Fix Caps issues --- internal/service/elbv2/listener_rule.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/service/elbv2/listener_rule.go b/internal/service/elbv2/listener_rule.go index 90353f73bd83..e51fff04dbe9 100644 --- a/internal/service/elbv2/listener_rule.go +++ b/internal/service/elbv2/listener_rule.go @@ -612,7 +612,7 @@ func resourceListenerRuleRead(ctx context.Context, d *schema.ResourceData, meta conditionMap["host_header"] = []any{flattenHostHeaderConditionConfig(condition.HostHeaderConfig)} case "http-header": - conditionMap["http_header"] = []any{flattenHttpHeaderConditionConfig(condition.HttpHeaderConfig)} + conditionMap["http_header"] = []any{flattenHTTPHeaderConditionConfig(condition.HttpHeaderConfig)} case "http-request-method": conditionMap["http_request_method"] = []any{ @@ -879,7 +879,7 @@ func expandRuleConditions(tfList []any) ([]awstypes.RuleCondition, error) { field = "http-header" attrs += 1 - apiObjects[i].HttpHeaderConfig = expandHttpHeaderConditionConfig(httpHeader[0].(map[string]any)) + apiObjects[i].HttpHeaderConfig = expandHTTPHeaderConditionConfig(httpHeader[0].(map[string]any)) } if httpRequestMethod, ok := tfMap["http_request_method"].([]any); ok && len(httpRequestMethod) > 0 { @@ -960,7 +960,7 @@ func expandHostHeaderConditionConfig(tfMap map[string]any) *awstypes.HostHeaderC return apiObject } -func expandHttpHeaderConditionConfig(tfMap map[string]any) *awstypes.HttpHeaderConditionConfig { +func expandHTTPHeaderConditionConfig(tfMap map[string]any) *awstypes.HttpHeaderConditionConfig { if tfMap == nil { return nil } @@ -1009,7 +1009,7 @@ func flattenHostHeaderConditionConfig(apiObject *awstypes.HostHeaderConditionCon return tfMap } -func flattenHttpHeaderConditionConfig(apiObject *awstypes.HttpHeaderConditionConfig) map[string]any { +func flattenHTTPHeaderConditionConfig(apiObject *awstypes.HttpHeaderConditionConfig) map[string]any { if apiObject == nil { return nil } From 966941ebcb1379823d4056c6be7c685e961e70d3 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 09:58:24 +0900 Subject: [PATCH 08/11] add changelog --- .changelog/44741.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changelog/44741.txt diff --git a/.changelog/44741.txt b/.changelog/44741.txt new file mode 100644 index 000000000000..1b582c031a0f --- /dev/null +++ b/.changelog/44741.txt @@ -0,0 +1,11 @@ +```release-note:enhancement +resource/aws_lb_listener_rule: Add `regex_values` arguments to `host_header`, `http_header` and `path_pattern` blocks within `condition` block +``` + +```release-note:enhancement +resource/aws_lb_listener_rule: Change `values` arguments in `host_header`, `http_header` and `path_pattern` blocks within `condition` block from `Required` to `Optional` +``` + +```release-note:enhancement +data-source/aws_lb_listener_rule: Add `regex_values` attributes to `host_header`, `http_header` and `path_pattern` blocks within `condition` block +``` From fbe462ab0f93ce6d743d4ba58c5175d13670fd97 Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 10:02:30 +0900 Subject: [PATCH 09/11] docs: Fix format --- website/docs/r/lb_listener_rule.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/r/lb_listener_rule.html.markdown b/website/docs/r/lb_listener_rule.html.markdown index 32e00e288f95..262b599cea3a 100644 --- a/website/docs/r/lb_listener_rule.html.markdown +++ b/website/docs/r/lb_listener_rule.html.markdown @@ -330,6 +330,8 @@ HTTP Header Blocks (for `http_header`) support the following: #### Path Pattern Blocks +Path Pattern Blocks (for `path_pattern`) support the following: + * `regex_values` - (Optional) List of regular expressions to compare against the request URL. The maximum length of each string is 128 characters. Conflicts with `values`. * `values` - (Optional) List of path patterns to compare against the request URL. Maximum size of each pattern is 128 characters. Comparison is case-sensitive. Wildcard characters supported: * (matches 0 or more characters) and ? (matches exactly 1 character). Only one pattern needs to match for the condition to be satisfied. Path pattern is compared only to the path of the URL, not to its query string. To compare against the query string, use a `query_string` condition. Conflicts with `regex_values`. From 3b3b80616d4687c412ddfb49c0345f42a7a32afe Mon Sep 17 00:00:00 2001 From: tabito Date: Tue, 21 Oct 2025 10:26:04 +0900 Subject: [PATCH 10/11] acctest: add checks for regex_values --- internal/service/elbv2/listener_rule_data_source_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/service/elbv2/listener_rule_data_source_test.go b/internal/service/elbv2/listener_rule_data_source_test.go index ca0d0d067fb3..c9986317b19d 100644 --- a/internal/service/elbv2/listener_rule_data_source_test.go +++ b/internal/service/elbv2/listener_rule_data_source_test.go @@ -93,6 +93,7 @@ func TestAccELBV2ListenerRuleDataSource_byARN(t *testing.T) { statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ expectKnownCondition("host_header", knownvalue.ListExact([]knownvalue.Check{ knownvalue.ObjectExact(map[string]knownvalue.Check{ + "regex_values": knownvalue.Null(), names.AttrValues: knownvalue.SetExact([]knownvalue.Check{ knownvalue.StringExact("example.com"), }), @@ -183,6 +184,7 @@ func TestAccELBV2ListenerRuleDataSource_byListenerAndPriority(t *testing.T) { statecheck.ExpectKnownValue(dataSourceName, tfjsonpath.New(names.AttrCondition), knownvalue.SetExact([]knownvalue.Check{ expectKnownCondition("host_header", knownvalue.ListExact([]knownvalue.Check{ knownvalue.ObjectExact(map[string]knownvalue.Check{ + "regex_values": knownvalue.Null(), names.AttrValues: knownvalue.SetExact([]knownvalue.Check{ knownvalue.StringExact("example.com"), }), From 62b98a997ff224c9318d8633e6846daa680a865f Mon Sep 17 00:00:00 2001 From: Jared Baker Date: Mon, 27 Oct 2025 11:30:21 -0400 Subject: [PATCH 11/11] chore: tweak changelog --- .changelog/44741.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.changelog/44741.txt b/.changelog/44741.txt index 1b582c031a0f..f617fd0f6956 100644 --- a/.changelog/44741.txt +++ b/.changelog/44741.txt @@ -1,11 +1,11 @@ ```release-note:enhancement -resource/aws_lb_listener_rule: Add `regex_values` arguments to `host_header`, `http_header` and `path_pattern` blocks within `condition` block +resource/aws_lb_listener_rule: Add `regex_values` argument to `condition.host_header`, `condition.http_header` and `condition.path_pattern` blocks ``` ```release-note:enhancement -resource/aws_lb_listener_rule: Change `values` arguments in `host_header`, `http_header` and `path_pattern` blocks within `condition` block from `Required` to `Optional` +resource/aws_lb_listener_rule: The `values` argument in `condition.host_header`, `condition.http_header` and `condition.path_pattern` is now optional ``` ```release-note:enhancement -data-source/aws_lb_listener_rule: Add `regex_values` attributes to `host_header`, `http_header` and `path_pattern` blocks within `condition` block +data-source/aws_lb_listener_rule: Add `regex_values` attribute to `condition.host_header`, `condition.http_header` and `condition.path_pattern` blocks ```