diff --git a/.changelog/8709.txt b/.changelog/8709.txt new file mode 100644 index 00000000000..ef7f3ed6f1b --- /dev/null +++ b/.changelog/8709.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +monitoring: added `synthetic_monitor` to `google_monitoring_uptime_check_config` resource +``` diff --git a/google/services/monitoring/resource_monitoring_uptime_check_config.go b/google/services/monitoring/resource_monitoring_uptime_check_config.go index 854b32fe6b1..5f3dbf0a121 100644 --- a/google/services/monitoring/resource_monitoring_uptime_check_config.go +++ b/google/services/monitoring/resource_monitoring_uptime_check_config.go @@ -224,7 +224,6 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource { }, }, }, - ExactlyOneOf: []string{"http_check", "tcp_check"}, }, "monitored_resource": { Type: schema.TypeList, @@ -249,7 +248,7 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource { }, }, }, - ExactlyOneOf: []string{"monitored_resource", "resource_group"}, + ExactlyOneOf: []string{"monitored_resource", "resource_group", "synthetic_monitor"}, }, "period": { Type: schema.TypeString, @@ -283,7 +282,7 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource { }, }, }, - ExactlyOneOf: []string{"monitored_resource", "resource_group"}, + ExactlyOneOf: []string{"monitored_resource", "resource_group", "synthetic_monitor"}, }, "selected_regions": { Type: schema.TypeList, @@ -293,6 +292,36 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource { Type: schema.TypeString, }, }, + "synthetic_monitor": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `A Synthetic Monitor deployed to a Cloud Functions V2 instance.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cloud_function_v2": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Description: `Target a Synthetic Monitor GCFv2 Instance`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The fully qualified name of the cloud function resource.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + }, + }, + ExactlyOneOf: []string{"monitored_resource", "resource_group", "synthetic_monitor"}, + }, "tcp_check": { Type: schema.TypeList, Optional: true, @@ -307,7 +336,6 @@ func ResourceMonitoringUptimeCheckConfig() *schema.Resource { }, }, }, - ExactlyOneOf: []string{"http_check", "tcp_check"}, }, "name": { Type: schema.TypeString, @@ -398,6 +426,12 @@ func resourceMonitoringUptimeCheckConfigCreate(d *schema.ResourceData, meta inte } else if v, ok := d.GetOkExists("monitored_resource"); !tpgresource.IsEmptyValue(reflect.ValueOf(monitoredResourceProp)) && (ok || !reflect.DeepEqual(v, monitoredResourceProp)) { obj["monitoredResource"] = monitoredResourceProp } + syntheticMonitorProp, err := expandMonitoringUptimeCheckConfigSyntheticMonitor(d.Get("synthetic_monitor"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("synthetic_monitor"); !tpgresource.IsEmptyValue(reflect.ValueOf(syntheticMonitorProp)) && (ok || !reflect.DeepEqual(v, syntheticMonitorProp)) { + obj["syntheticMonitor"] = syntheticMonitorProp + } lockName, err := tpgresource.ReplaceVars(d, config, "stackdriver/groups/{{project}}") if err != nil { @@ -549,6 +583,9 @@ func resourceMonitoringUptimeCheckConfigRead(d *schema.ResourceData, meta interf if err := d.Set("monitored_resource", flattenMonitoringUptimeCheckConfigMonitoredResource(res["monitoredResource"], d, config)); err != nil { return fmt.Errorf("Error reading UptimeCheckConfig: %s", err) } + if err := d.Set("synthetic_monitor", flattenMonitoringUptimeCheckConfigSyntheticMonitor(res["syntheticMonitor"], d, config)); err != nil { + return fmt.Errorf("Error reading UptimeCheckConfig: %s", err) + } return nil } @@ -1053,6 +1090,36 @@ func flattenMonitoringUptimeCheckConfigMonitoredResourceLabels(v interface{}, d return v } +func flattenMonitoringUptimeCheckConfigSyntheticMonitor(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["cloud_function_v2"] = + flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(original["cloudFunctionV2"], d, config) + return []interface{}{transformed} +} +func flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["name"] = + flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(original["name"], d, config) + return []interface{}{transformed} +} +func flattenMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func expandMonitoringUptimeCheckConfigDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } @@ -1451,3 +1518,45 @@ func expandMonitoringUptimeCheckConfigMonitoredResourceLabels(v interface{}, d t } return m, nil } + +func expandMonitoringUptimeCheckConfigSyntheticMonitor(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedCloudFunctionV2, err := expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(original["cloud_function_v2"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCloudFunctionV2); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["cloudFunctionV2"] = transformedCloudFunctionV2 + } + + return transformed, nil +} + +func expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedName, err := expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["name"] = transformedName + } + + return transformed, nil +} + +func expandMonitoringUptimeCheckConfigSyntheticMonitorCloudFunctionV2Name(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/google/services/monitoring/resource_monitoring_uptime_check_config_generated_test.go b/google/services/monitoring/resource_monitoring_uptime_check_config_generated_test.go index f78bace2912..641501eb250 100644 --- a/google/services/monitoring/resource_monitoring_uptime_check_config_generated_test.go +++ b/google/services/monitoring/resource_monitoring_uptime_check_config_generated_test.go @@ -268,6 +268,81 @@ resource "google_monitoring_group" "check" { `, context) } +func TestAccMonitoringUptimeCheckConfig_uptimeCheckConfigSyntheticMonitorExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "zip_path": "./test-fixtures/synthetic-fn-source.zip", + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccMonitoringUptimeCheckConfig_uptimeCheckConfigSyntheticMonitorExample(context), + }, + { + ResourceName: "google_monitoring_uptime_check_config.synthetic_monitor", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccMonitoringUptimeCheckConfig_uptimeCheckConfigSyntheticMonitorExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_storage_bucket" "bucket" { + name = "%{project_id}-tf-test-gcf-source%{random_suffix}" # Every bucket name must be globally unique + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + name = "function-source.zip" + bucket = google_storage_bucket.bucket.name + source = "%{zip_path}" # Add path to the zipped function source code +} + +resource "google_cloudfunctions2_function" "function" { + name = "tf_test_synthetic_function%{random_suffix}" + location = "us-central1" + + build_config { + runtime = "nodejs16" + entry_point = "SyntheticFunction" # Set the entry point + source { + storage_source { + bucket = google_storage_bucket.bucket.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } +} + +resource "google_monitoring_uptime_check_config" "synthetic_monitor" { + display_name = "tf_test_synthetic_monitor%{random_suffix}" + timeout = "60s" + + synthetic_monitor { + cloud_function_v2 { + name = google_cloudfunctions2_function.function.id + } + } +} +`, context) +} + func testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/google/services/monitoring/test-fixtures/synthetic-fn-source.zip b/google/services/monitoring/test-fixtures/synthetic-fn-source.zip new file mode 100644 index 00000000000..fd79909197a Binary files /dev/null and b/google/services/monitoring/test-fixtures/synthetic-fn-source.zip differ diff --git a/website/docs/r/monitoring_uptime_check_config.html.markdown b/website/docs/r/monitoring_uptime_check_config.html.markdown index 15ae959de49..ec1d8218689 100644 --- a/website/docs/r/monitoring_uptime_check_config.html.markdown +++ b/website/docs/r/monitoring_uptime_check_config.html.markdown @@ -175,6 +175,55 @@ resource "google_monitoring_group" "check" { filter = "resource.metadata.name=has_substring(\"foo\")" } ``` +## Example Usage - Uptime Check Config Synthetic Monitor + + +```hcl +resource "google_storage_bucket" "bucket" { + name = "my-project-name-gcf-source" # Every bucket name must be globally unique + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + name = "function-source.zip" + bucket = google_storage_bucket.bucket.name + source = "synthetic-fn-source.zip" # Add path to the zipped function source code +} + +resource "google_cloudfunctions2_function" "function" { + name = "synthetic_function" + location = "us-central1" + + build_config { + runtime = "nodejs16" + entry_point = "SyntheticFunction" # Set the entry point + source { + storage_source { + bucket = google_storage_bucket.bucket.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } +} + +resource "google_monitoring_uptime_check_config" "synthetic_monitor" { + display_name = "synthetic_monitor" + timeout = "60s" + + synthetic_monitor { + cloud_function_v2 { + name = google_cloudfunctions2_function.function.id + } + } +} +``` ## Argument Reference @@ -231,6 +280,11 @@ The following arguments are supported: 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 Structure is [documented below](#nested_monitored_resource). +* `synthetic_monitor` - + (Optional) + A Synthetic Monitor deployed to a Cloud Functions V2 instance. + Structure is [documented below](#nested_synthetic_monitor). + * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. @@ -366,6 +420,20 @@ The following arguments are supported: (Required) 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". +The `synthetic_monitor` block supports: + +* `cloud_function_v2` - + (Required) + Target a Synthetic Monitor GCFv2 Instance + Structure is [documented below](#nested_cloud_function_v2). + + +The `cloud_function_v2` block supports: + +* `name` - + (Required) + The fully qualified name of the cloud function resource. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: