Skip to content

Commit e2a76cd

Browse files
Adding JSONPath content matching fields. (#6082) (#11829)
* Adding JSONPath content matching fields. * Make json_path required if including json_path_matcher Signed-off-by: Modular Magician <[email protected]>
1 parent f14c3a9 commit e2a76cd

5 files changed

+203
-11
lines changed

.changelog/6082.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
monitoring: added support for JSONPath content matchers for Uptime Checks
3+
```

google/resource_monitoring_uptime_check_config.go

+92-5
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,33 @@ func resourceMonitoringUptimeCheckConfig() *schema.Resource {
7575
Required: true,
7676
Description: `String or regex content to match (max 1024 bytes)`,
7777
},
78+
"json_path_matcher": {
79+
Type: schema.TypeList,
80+
Optional: true,
81+
Description: `Information needed to perform a JSONPath content match. Used for 'ContentMatcherOption::MATCHES_JSON_PATH' and 'ContentMatcherOption::NOT_MATCHES_JSON_PATH'.`,
82+
MaxItems: 1,
83+
Elem: &schema.Resource{
84+
Schema: map[string]*schema.Schema{
85+
"json_path": {
86+
Type: schema.TypeString,
87+
Required: true,
88+
Description: `JSONPath within the response output pointing to the expected 'ContentMatcher::content' to match against.`,
89+
},
90+
"json_matcher": {
91+
Type: schema.TypeString,
92+
Optional: true,
93+
ValidateFunc: validateEnum([]string{"EXACT_MATCH", "REGEX_MATCH", ""}),
94+
Description: `Options to perform JSONPath content matching. Default value: "EXACT_MATCH" Possible values: ["EXACT_MATCH", "REGEX_MATCH"]`,
95+
Default: "EXACT_MATCH",
96+
},
97+
},
98+
},
99+
},
78100
"matcher": {
79101
Type: schema.TypeString,
80102
Optional: true,
81-
ValidateFunc: validateEnum([]string{"CONTAINS_STRING", "NOT_CONTAINS_STRING", "MATCHES_REGEX", "NOT_MATCHES_REGEX", ""}),
82-
Description: `The type of content matcher that will be applied to the server output, compared to the content string when the check is run. Default value: "CONTAINS_STRING" Possible values: ["CONTAINS_STRING", "NOT_CONTAINS_STRING", "MATCHES_REGEX", "NOT_MATCHES_REGEX"]`,
103+
ValidateFunc: validateEnum([]string{"CONTAINS_STRING", "NOT_CONTAINS_STRING", "MATCHES_REGEX", "NOT_MATCHES_REGEX", "MATCHES_JSON_PATH", "NOT_MATCHES_JSON_PATH", ""}),
104+
Description: `The type of content matcher that will be applied to the server output, compared to the content string when the check is run. Default value: "CONTAINS_STRING" Possible values: ["CONTAINS_STRING", "NOT_CONTAINS_STRING", "MATCHES_REGEX", "NOT_MATCHES_REGEX", "MATCHES_JSON_PATH", "NOT_MATCHES_JSON_PATH"]`,
83105
Default: "CONTAINS_STRING",
84106
},
85107
},
@@ -181,7 +203,7 @@ func resourceMonitoringUptimeCheckConfig() *schema.Resource {
181203
Type: schema.TypeList,
182204
Optional: true,
183205
ForceNew: true,
184-
Description: `The monitored resource (https://cloud.google.com/monitoring/api/resources) associated with the configuration. The following monitored resource types are supported for uptime checks: uptime_url gce_instance gae_app aws_ec2_instance aws_elb_load_balancer`,
206+
Description: `The monitored resource (https://cloud.google.com/monitoring/api/resources) associated with the configuration. The following monitored resource types are supported for uptime checks: uptime_url gce_instance gae_app aws_ec2_instance aws_elb_load_balancer k8s_service servicedirectory_service`,
185207
MaxItems: 1,
186208
Elem: &schema.Resource{
187209
Schema: map[string]*schema.Schema{
@@ -693,8 +715,9 @@ func flattenMonitoringUptimeCheckConfigContentMatchers(v interface{}, d *schema.
693715
continue
694716
}
695717
transformed = append(transformed, map[string]interface{}{
696-
"content": flattenMonitoringUptimeCheckConfigContentMatchersContent(original["content"], d, config),
697-
"matcher": flattenMonitoringUptimeCheckConfigContentMatchersMatcher(original["matcher"], d, config),
718+
"content": flattenMonitoringUptimeCheckConfigContentMatchersContent(original["content"], d, config),
719+
"matcher": flattenMonitoringUptimeCheckConfigContentMatchersMatcher(original["matcher"], d, config),
720+
"json_path_matcher": flattenMonitoringUptimeCheckConfigContentMatchersJsonPathMatcher(original["jsonPathMatcher"], d, config),
698721
})
699722
}
700723
return transformed
@@ -707,6 +730,29 @@ func flattenMonitoringUptimeCheckConfigContentMatchersMatcher(v interface{}, d *
707730
return v
708731
}
709732

733+
func flattenMonitoringUptimeCheckConfigContentMatchersJsonPathMatcher(v interface{}, d *schema.ResourceData, config *Config) interface{} {
734+
if v == nil {
735+
return nil
736+
}
737+
original := v.(map[string]interface{})
738+
if len(original) == 0 {
739+
return nil
740+
}
741+
transformed := make(map[string]interface{})
742+
transformed["json_path"] =
743+
flattenMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonPath(original["jsonPath"], d, config)
744+
transformed["json_matcher"] =
745+
flattenMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonMatcher(original["jsonMatcher"], d, config)
746+
return []interface{}{transformed}
747+
}
748+
func flattenMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonPath(v interface{}, d *schema.ResourceData, config *Config) interface{} {
749+
return v
750+
}
751+
752+
func flattenMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonMatcher(v interface{}, d *schema.ResourceData, config *Config) interface{} {
753+
return v
754+
}
755+
710756
func flattenMonitoringUptimeCheckConfigSelectedRegions(v interface{}, d *schema.ResourceData, config *Config) interface{} {
711757
return v
712758
}
@@ -931,6 +977,13 @@ func expandMonitoringUptimeCheckConfigContentMatchers(v interface{}, d Terraform
931977
transformed["matcher"] = transformedMatcher
932978
}
933979

980+
transformedJsonPathMatcher, err := expandMonitoringUptimeCheckConfigContentMatchersJsonPathMatcher(original["json_path_matcher"], d, config)
981+
if err != nil {
982+
return nil, err
983+
} else if val := reflect.ValueOf(transformedJsonPathMatcher); val.IsValid() && !isEmptyValue(val) {
984+
transformed["jsonPathMatcher"] = transformedJsonPathMatcher
985+
}
986+
934987
req = append(req, transformed)
935988
}
936989
return req, nil
@@ -944,6 +997,40 @@ func expandMonitoringUptimeCheckConfigContentMatchersMatcher(v interface{}, d Te
944997
return v, nil
945998
}
946999

1000+
func expandMonitoringUptimeCheckConfigContentMatchersJsonPathMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
1001+
l := v.([]interface{})
1002+
if len(l) == 0 || l[0] == nil {
1003+
return nil, nil
1004+
}
1005+
raw := l[0]
1006+
original := raw.(map[string]interface{})
1007+
transformed := make(map[string]interface{})
1008+
1009+
transformedJsonPath, err := expandMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonPath(original["json_path"], d, config)
1010+
if err != nil {
1011+
return nil, err
1012+
} else if val := reflect.ValueOf(transformedJsonPath); val.IsValid() && !isEmptyValue(val) {
1013+
transformed["jsonPath"] = transformedJsonPath
1014+
}
1015+
1016+
transformedJsonMatcher, err := expandMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonMatcher(original["json_matcher"], d, config)
1017+
if err != nil {
1018+
return nil, err
1019+
} else if val := reflect.ValueOf(transformedJsonMatcher); val.IsValid() && !isEmptyValue(val) {
1020+
transformed["jsonMatcher"] = transformedJsonMatcher
1021+
}
1022+
1023+
return transformed, nil
1024+
}
1025+
1026+
func expandMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonPath(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
1027+
return v, nil
1028+
}
1029+
1030+
func expandMonitoringUptimeCheckConfigContentMatchersJsonPathMatcherJsonMatcher(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
1031+
return v, nil
1032+
}
1033+
9471034
func expandMonitoringUptimeCheckConfigSelectedRegions(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
9481035
return v, nil
9491036
}

google/resource_monitoring_uptime_check_config_generated_test.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ resource "google_monitoring_uptime_check_config" "http" {
7171
}
7272
7373
content_matchers {
74-
content = "example"
74+
content = "\"example\""
75+
matcher = "MATCHES_JSON_PATH"
76+
json_path_matcher {
77+
json_path = "$.path"
78+
json_matcher = "EXACT_MATCH"
79+
}
7580
}
7681
7782
checker_type = "STATIC_IP_CHECKERS"
@@ -127,6 +132,11 @@ resource "google_monitoring_uptime_check_config" "https" {
127132
128133
content_matchers {
129134
content = "example"
135+
matcher = "MATCHES_JSON_PATH"
136+
json_path_matcher {
137+
json_path = "$.path"
138+
json_matcher = "REGEX_MATCH"
139+
}
130140
}
131141
}
132142
`, context)

google/resource_monitoring_uptime_check_config_test.go

+66-2
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,38 @@ func TestAccMonitoringUptimeCheckConfig_changeNonUpdatableFields(t *testing.T) {
8181
})
8282
}
8383

84-
func testAccMonitoringUptimeCheckConfig_update(suffix, path, project, pwd, host string) string {
84+
func TestAccMonitoringUptimeCheckConfig_jsonPathUpdate(t *testing.T) {
85+
t.Parallel()
86+
project := getTestProjectFromEnv()
87+
host := "192.168.1.1"
88+
suffix := randString(t, 4)
89+
90+
vcrTest(t, resource.TestCase{
91+
PreCheck: func() { testAccPreCheck(t) },
92+
Providers: testAccProviders,
93+
CheckDestroy: testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t),
94+
Steps: []resource.TestStep{
95+
{
96+
Config: testAccMonitoringUptimeCheckConfig_jsonPathUpdate(suffix, project, host, "123", "$.path", "EXACT_MATCH"),
97+
},
98+
{
99+
ResourceName: "google_monitoring_uptime_check_config.http",
100+
ImportState: true,
101+
ImportStateVerify: true,
102+
},
103+
{
104+
Config: testAccMonitoringUptimeCheckConfig_jsonPathUpdate(suffix, project, host, "content", "$.different", "REGEX_MATCH"),
105+
},
106+
{
107+
ResourceName: "google_monitoring_uptime_check_config.http",
108+
ImportState: true,
109+
ImportStateVerify: true,
110+
},
111+
},
112+
})
113+
}
114+
115+
func testAccMonitoringUptimeCheckConfig_update(suffix, path, pwd, project, host string) string {
85116
return fmt.Sprintf(`
86117
resource "google_monitoring_uptime_check_config" "http" {
87118
display_name = "http-uptime-check-%s"
@@ -110,6 +141,39 @@ resource "google_monitoring_uptime_check_config" "http" {
110141
matcher = "CONTAINS_STRING"
111142
}
112143
}
113-
`, suffix, path, project, pwd, host,
144+
`, suffix, path, pwd, project, host,
145+
)
146+
}
147+
148+
func testAccMonitoringUptimeCheckConfig_jsonPathUpdate(suffix, project, host, content, json_path, json_path_matcher string) string {
149+
return fmt.Sprintf(`
150+
resource "google_monitoring_uptime_check_config" "http" {
151+
display_name = "http-uptime-check-%s"
152+
timeout = "60s"
153+
154+
http_check {
155+
path = "a-path"
156+
port = "80"
157+
request_method = "GET"
158+
}
159+
160+
monitored_resource {
161+
type = "uptime_url"
162+
labels = {
163+
project_id = "%s"
164+
host = "%s"
165+
}
166+
}
167+
168+
content_matchers {
169+
content = "%s"
170+
matcher = "MATCHES_JSON_PATH"
171+
json_path_matcher {
172+
json_path = "%s"
173+
json_matcher = "%s"
174+
}
175+
}
176+
}
177+
`, suffix, project, host, content, json_path, json_path_matcher,
114178
)
115179
}

website/docs/r/monitoring_uptime_check_config.html.markdown

+31-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ resource "google_monitoring_uptime_check_config" "http" {
5959
}
6060
6161
content_matchers {
62-
content = "example"
62+
content = "\"example\""
63+
matcher = "MATCHES_JSON_PATH"
64+
json_path_matcher {
65+
json_path = "$.path"
66+
json_matcher = "EXACT_MATCH"
67+
}
6368
}
6469
6570
checker_type = "STATIC_IP_CHECKERS"
@@ -90,6 +95,11 @@ resource "google_monitoring_uptime_check_config" "https" {
9095
9196
content_matchers {
9297
content = "example"
98+
matcher = "MATCHES_JSON_PATH"
99+
json_path_matcher {
100+
json_path = "$.path"
101+
json_matcher = "REGEX_MATCH"
102+
}
93103
}
94104
}
95105
```
@@ -174,7 +184,7 @@ The following arguments are supported:
174184

175185
* `monitored_resource` -
176186
(Optional)
177-
The monitored resource (https://cloud.google.com/monitoring/api/resources) associated with the configuration. The following monitored resource types are supported for uptime checks: uptime_url gce_instance gae_app aws_ec2_instance aws_elb_load_balancer
187+
The monitored resource (https://cloud.google.com/monitoring/api/resources) associated with the configuration. The following monitored resource types are supported for uptime checks: uptime_url gce_instance gae_app aws_ec2_instance aws_elb_load_balancer k8s_service servicedirectory_service
178188
Structure is [documented below](#nested_monitored_resource).
179189

180190
* `project` - (Optional) The ID of the project in which the resource belongs.
@@ -191,7 +201,25 @@ The following arguments are supported:
191201
(Optional)
192202
The type of content matcher that will be applied to the server output, compared to the content string when the check is run.
193203
Default value is `CONTAINS_STRING`.
194-
Possible values are `CONTAINS_STRING`, `NOT_CONTAINS_STRING`, `MATCHES_REGEX`, and `NOT_MATCHES_REGEX`.
204+
Possible values are `CONTAINS_STRING`, `NOT_CONTAINS_STRING`, `MATCHES_REGEX`, `NOT_MATCHES_REGEX`, `MATCHES_JSON_PATH`, and `NOT_MATCHES_JSON_PATH`.
205+
206+
* `json_path_matcher` -
207+
(Optional)
208+
Information needed to perform a JSONPath content match. Used for `ContentMatcherOption::MATCHES_JSON_PATH` and `ContentMatcherOption::NOT_MATCHES_JSON_PATH`.
209+
Structure is [documented below](#nested_json_path_matcher).
210+
211+
212+
<a name="nested_json_path_matcher"></a>The `json_path_matcher` block supports:
213+
214+
* `json_path` -
215+
(Required)
216+
JSONPath within the response output pointing to the expected `ContentMatcher::content` to match against.
217+
218+
* `json_matcher` -
219+
(Optional)
220+
Options to perform JSONPath content matching.
221+
Default value is `EXACT_MATCH`.
222+
Possible values are `EXACT_MATCH` and `REGEX_MATCH`.
195223

196224
<a name="nested_http_check"></a>The `http_check` block supports:
197225

0 commit comments

Comments
 (0)