Skip to content

Commit a948669

Browse files
Adds the synthetic monitor target type as an option for uptime checks. (#8709) (#15623)
* Adds synthetic_monitor type that lives alongside resource_group and monitored_resource * removes requirement for either tcp_check or http_check to be provided, as neither is required when synthetic_monitor is provided * Adds acceptance test, and example. A new test fixutre w/ zip file is provided for these flows. Signed-off-by: Modular Magician <[email protected]>
1 parent 0e253e0 commit a948669

File tree

5 files changed

+259
-4
lines changed

5 files changed

+259
-4
lines changed

.changelog/8709.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
monitoring: added `synthetic_monitor` to `google_monitoring_uptime_check_config` resource
3+
```

google/services/monitoring/resource_monitoring_uptime_check_config.go

+113-4
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource {
224224
},
225225
},
226226
},
227-
ExactlyOneOf: []string{"http_check", "tcp_check"},
228227
},
229228
"monitored_resource": {
230229
Type: schema.TypeList,
@@ -249,7 +248,7 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource {
249248
},
250249
},
251250
},
252-
ExactlyOneOf: []string{"monitored_resource", "resource_group"},
251+
ExactlyOneOf: []string{"monitored_resource", "resource_group", "synthetic_monitor"},
253252
},
254253
"period": {
255254
Type: schema.TypeString,
@@ -283,7 +282,7 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource {
283282
},
284283
},
285284
},
286-
ExactlyOneOf: []string{"monitored_resource", "resource_group"},
285+
ExactlyOneOf: []string{"monitored_resource", "resource_group", "synthetic_monitor"},
287286
},
288287
"selected_regions": {
289288
Type: schema.TypeList,
@@ -293,6 +292,36 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource {
293292
Type: schema.TypeString,
294293
},
295294
},
295+
"synthetic_monitor": {
296+
Type: schema.TypeList,
297+
Optional: true,
298+
ForceNew: true,
299+
Description: `A Synthetic Monitor deployed to a Cloud Functions V2 instance.`,
300+
MaxItems: 1,
301+
Elem: &schema.Resource{
302+
Schema: map[string]*schema.Schema{
303+
"cloud_function_v2": {
304+
Type: schema.TypeList,
305+
Required: true,
306+
ForceNew: true,
307+
Description: `Target a Synthetic Monitor GCFv2 Instance`,
308+
MaxItems: 1,
309+
Elem: &schema.Resource{
310+
Schema: map[string]*schema.Schema{
311+
"name": {
312+
Type: schema.TypeString,
313+
Required: true,
314+
ForceNew: true,
315+
Description: `The fully qualified name of the cloud function resource.`,
316+
},
317+
},
318+
},
319+
ExactlyOneOf: []string{},
320+
},
321+
},
322+
},
323+
ExactlyOneOf: []string{"monitored_resource", "resource_group", "synthetic_monitor"},
324+
},
296325
"tcp_check": {
297326
Type: schema.TypeList,
298327
Optional: true,
@@ -307,7 +336,6 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource {
307336
},
308337
},
309338
},
310-
ExactlyOneOf: []string{"http_check", "tcp_check"},
311339
},
312340
"name": {
313341
Type: schema.TypeString,
@@ -398,6 +426,12 @@ func resourceMonitoringUptimeCheckConfigCreate(d *schema.ResourceData, meta inte
398426
} else if v, ok := d.GetOkExists("monitored_resource"); !tpgresource.IsEmptyValue(reflect.ValueOf(monitoredResourceProp)) && (ok || !reflect.DeepEqual(v, monitoredResourceProp)) {
399427
obj["monitoredResource"] = monitoredResourceProp
400428
}
429+
syntheticMonitorProp, err := expandMonitoringUptimeCheckConfigSyntheticMonitor(d.Get("synthetic_monitor"), d, config)
430+
if err != nil {
431+
return err
432+
} else if v, ok := d.GetOkExists("synthetic_monitor"); !tpgresource.IsEmptyValue(reflect.ValueOf(syntheticMonitorProp)) && (ok || !reflect.DeepEqual(v, syntheticMonitorProp)) {
433+
obj["syntheticMonitor"] = syntheticMonitorProp
434+
}
401435

402436
lockName, err := tpgresource.ReplaceVars(d, config, "stackdriver/groups/{{project}}")
403437
if err != nil {
@@ -549,6 +583,9 @@ func resourceMonitoringUptimeCheckConfigRead(d *schema.ResourceData, meta interf
549583
if err := d.Set("monitored_resource", flattenMonitoringUptimeCheckConfigMonitoredResource(res["monitoredResource"], d, config)); err != nil {
550584
return fmt.Errorf("Error reading UptimeCheckConfig: %s", err)
551585
}
586+
if err := d.Set("synthetic_monitor", flattenMonitoringUptimeCheckConfigSyntheticMonitor(res["syntheticMonitor"], d, config)); err != nil {
587+
return fmt.Errorf("Error reading UptimeCheckConfig: %s", err)
588+
}
552589

553590
return nil
554591
}
@@ -1053,6 +1090,36 @@ func flattenMonitoringUptimeCheckConfigMonitoredResourceLabels(v interface{}, d
10531090
return v
10541091
}
10551092

1093+
func flattenMonitoringUptimeCheckConfigSyntheticMonitor(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1094+
if v == nil {
1095+
return nil
1096+
}
1097+
original := v.(map[string]interface{})
1098+
if len(original) == 0 {
1099+
return nil
1100+
}
1101+
transformed := make(map[string]interface{})
1102+
transformed["cloud_function_v2"] =
1103+
flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(original["cloudFunctionV2"], d, config)
1104+
return []interface{}{transformed}
1105+
}
1106+
func flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1107+
if v == nil {
1108+
return nil
1109+
}
1110+
original := v.(map[string]interface{})
1111+
if len(original) == 0 {
1112+
return nil
1113+
}
1114+
transformed := make(map[string]interface{})
1115+
transformed["name"] =
1116+
flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(original["name"], d, config)
1117+
return []interface{}{transformed}
1118+
}
1119+
func flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1120+
return v
1121+
}
1122+
10561123
func expandMonitoringUptimeCheckConfigDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
10571124
return v, nil
10581125
}
@@ -1451,3 +1518,45 @@ func expandMonitoringUptimeCheckConfigMonitoredResourceLabels(v interface{}, d t
14511518
}
14521519
return m, nil
14531520
}
1521+
1522+
func expandMonitoringUptimeCheckConfigSyntheticMonitor(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1523+
l := v.([]interface{})
1524+
if len(l) == 0 || l[0] == nil {
1525+
return nil, nil
1526+
}
1527+
raw := l[0]
1528+
original := raw.(map[string]interface{})
1529+
transformed := make(map[string]interface{})
1530+
1531+
transformedCloudFunctionV2, err := expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(original["cloud_function_v2"], d, config)
1532+
if err != nil {
1533+
return nil, err
1534+
} else if val := reflect.ValueOf(transformedCloudFunctionV2); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1535+
transformed["cloudFunctionV2"] = transformedCloudFunctionV2
1536+
}
1537+
1538+
return transformed, nil
1539+
}
1540+
1541+
func expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1542+
l := v.([]interface{})
1543+
if len(l) == 0 || l[0] == nil {
1544+
return nil, nil
1545+
}
1546+
raw := l[0]
1547+
original := raw.(map[string]interface{})
1548+
transformed := make(map[string]interface{})
1549+
1550+
transformedName, err := expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(original["name"], d, config)
1551+
if err != nil {
1552+
return nil, err
1553+
} else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1554+
transformed["name"] = transformedName
1555+
}
1556+
1557+
return transformed, nil
1558+
}
1559+
1560+
func expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1561+
return v, nil
1562+
}

google/services/monitoring/resource_monitoring_uptime_check_config_generated_test.go

+75
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,81 @@ resource "google_monitoring_group" "check" {
268268
`, context)
269269
}
270270

271+
func TestAccMonitoringUptimeCheckConfig_uptimeCheckConfigSyntheticMonitorExample(t *testing.T) {
272+
t.Parallel()
273+
274+
context := map[string]interface{}{
275+
"project_id": envvar.GetTestProjectFromEnv(),
276+
"zip_path": "./test-fixtures/synthetic-fn-source.zip",
277+
"random_suffix": acctest.RandString(t, 10),
278+
}
279+
280+
acctest.VcrTest(t, resource.TestCase{
281+
PreCheck: func() { acctest.AccTestPreCheck(t) },
282+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
283+
CheckDestroy: testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t),
284+
Steps: []resource.TestStep{
285+
{
286+
Config: testAccMonitoringUptimeCheckConfig_uptimeCheckConfigSyntheticMonitorExample(context),
287+
},
288+
{
289+
ResourceName: "google_monitoring_uptime_check_config.synthetic_monitor",
290+
ImportState: true,
291+
ImportStateVerify: true,
292+
},
293+
},
294+
})
295+
}
296+
297+
func testAccMonitoringUptimeCheckConfig_uptimeCheckConfigSyntheticMonitorExample(context map[string]interface{}) string {
298+
return acctest.Nprintf(`
299+
resource "google_storage_bucket" "bucket" {
300+
name = "%{project_id}-tf-test-gcf-source%{random_suffix}" # Every bucket name must be globally unique
301+
location = "US"
302+
uniform_bucket_level_access = true
303+
}
304+
305+
resource "google_storage_bucket_object" "object" {
306+
name = "function-source.zip"
307+
bucket = google_storage_bucket.bucket.name
308+
source = "%{zip_path}" # Add path to the zipped function source code
309+
}
310+
311+
resource "google_cloudfunctions2_function" "function" {
312+
name = "tf_test_synthetic_function%{random_suffix}"
313+
location = "us-central1"
314+
315+
build_config {
316+
runtime = "nodejs16"
317+
entry_point = "SyntheticFunction" # Set the entry point
318+
source {
319+
storage_source {
320+
bucket = google_storage_bucket.bucket.name
321+
object = google_storage_bucket_object.object.name
322+
}
323+
}
324+
}
325+
326+
service_config {
327+
max_instance_count = 1
328+
available_memory = "256M"
329+
timeout_seconds = 60
330+
}
331+
}
332+
333+
resource "google_monitoring_uptime_check_config" "synthetic_monitor" {
334+
display_name = "tf_test_synthetic_monitor%{random_suffix}"
335+
timeout = "60s"
336+
337+
synthetic_monitor {
338+
cloud_function_v2 {
339+
name = google_cloudfunctions2_function.function.id
340+
}
341+
}
342+
}
343+
`, context)
344+
}
345+
271346
func testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t *testing.T) func(s *terraform.State) error {
272347
return func(s *terraform.State) error {
273348
for name, rs := range s.RootModule().Resources {
Binary file not shown.

website/docs/r/monitoring_uptime_check_config.html.markdown

+68
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,55 @@ resource "google_monitoring_group" "check" {
175175
filter = "resource.metadata.name=has_substring(\"foo\")"
176176
}
177177
```
178+
## Example Usage - Uptime Check Config Synthetic Monitor
179+
180+
181+
```hcl
182+
resource "google_storage_bucket" "bucket" {
183+
name = "my-project-name-gcf-source" # Every bucket name must be globally unique
184+
location = "US"
185+
uniform_bucket_level_access = true
186+
}
187+
188+
resource "google_storage_bucket_object" "object" {
189+
name = "function-source.zip"
190+
bucket = google_storage_bucket.bucket.name
191+
source = "synthetic-fn-source.zip" # Add path to the zipped function source code
192+
}
193+
194+
resource "google_cloudfunctions2_function" "function" {
195+
name = "synthetic_function"
196+
location = "us-central1"
197+
198+
build_config {
199+
runtime = "nodejs16"
200+
entry_point = "SyntheticFunction" # Set the entry point
201+
source {
202+
storage_source {
203+
bucket = google_storage_bucket.bucket.name
204+
object = google_storage_bucket_object.object.name
205+
}
206+
}
207+
}
208+
209+
service_config {
210+
max_instance_count = 1
211+
available_memory = "256M"
212+
timeout_seconds = 60
213+
}
214+
}
215+
216+
resource "google_monitoring_uptime_check_config" "synthetic_monitor" {
217+
display_name = "synthetic_monitor"
218+
timeout = "60s"
219+
220+
synthetic_monitor {
221+
cloud_function_v2 {
222+
name = google_cloudfunctions2_function.function.id
223+
}
224+
}
225+
}
226+
```
178227

179228
## Argument Reference
180229

@@ -231,6 +280,11 @@ The following arguments are supported:
231280
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
232281
Structure is [documented below](#nested_monitored_resource).
233282

283+
* `synthetic_monitor` -
284+
(Optional)
285+
A Synthetic Monitor deployed to a Cloud Functions V2 instance.
286+
Structure is [documented below](#nested_synthetic_monitor).
287+
234288
* `project` - (Optional) The ID of the project in which the resource belongs.
235289
If it is not provided, the provider project is used.
236290

@@ -366,6 +420,20 @@ The following arguments are supported:
366420
(Required)
367421
Values for all of the labels listed in the associated monitored resource descriptor. For example, Compute Engine VM instances use the labels "project_id", "instance_id", and "zone".
368422

423+
<a name="nested_synthetic_monitor"></a>The `synthetic_monitor` block supports:
424+
425+
* `cloud_function_v2` -
426+
(Required)
427+
Target a Synthetic Monitor GCFv2 Instance
428+
Structure is [documented below](#nested_cloud_function_v2).
429+
430+
431+
<a name="nested_cloud_function_v2"></a>The `cloud_function_v2` block supports:
432+
433+
* `name` -
434+
(Required)
435+
The fully qualified name of the cloud function resource.
436+
369437
## Attributes Reference
370438

371439
In addition to the arguments listed above, the following computed attributes are exported:

0 commit comments

Comments
 (0)