From 81f2521293e0481641d72e20310653b731f23735 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Fri, 27 Sep 2019 22:40:29 -0500 Subject: [PATCH 01/25] New Resource: `azurerm_monitor_scheduled_query_rules` --- ...ta_source_monitor_scheduled_query_rules.go | 265 +++++++ ...urce_monitor_scheduled_query_rules_test.go | 243 +++++++ azurerm/internal/services/monitor/client.go | 5 + azurerm/provider.go | 2 + ...ource_arm_monitor_scheduled_query_rules.go | 685 ++++++++++++++++++ ..._arm_monitor_scheduled_query_rules_test.go | 320 ++++++++ ...onitor_scheduled_query_rules.html.markdown | 88 +++ ...onitor_scheduled_query_rules.html.markdown | 193 +++++ 8 files changed, 1801 insertions(+) create mode 100644 azurerm/data_source_monitor_scheduled_query_rules.go create mode 100644 azurerm/data_source_monitor_scheduled_query_rules_test.go create mode 100644 azurerm/resource_arm_monitor_scheduled_query_rules.go create mode 100644 azurerm/resource_arm_monitor_scheduled_query_rules_test.go create mode 100644 website/docs/d/monitor_scheduled_query_rules.html.markdown create mode 100644 website/docs/r/monitor_scheduled_query_rules.html.markdown diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go new file mode 100644 index 000000000000..7d551ed10437 --- /dev/null +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -0,0 +1,265 @@ +package azurerm + +import ( + "fmt" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmMonitorScheduledQueryRulesRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "action_type": { + Type: schema.TypeString, + Computed: true, + }, + "authorized_resources": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Computed: true, + }, + "email_subject": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Elem: schema.TypeString, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "values": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Computed: true, + }, + "query_type": { + Type: schema.TypeString, + Computed: true, + }, + "severity": { + Type: schema.TypeInt, + Computed: true, + }, + "throttling": { + Type: schema.TypeInt, + Computed: true, + }, + "time_window": { + Type: schema.TypeInt, + Computed: true, + }, + "trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Computed: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Computed: true, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} + +func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", *resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + switch action := resp.Action.(type) { + case insights.AlertingAction: + d.Set("action_type", "Alerting") + d.Set("azns_action", *action.AznsAction) + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", *action.ThrottlingInMin) + d.Set("trigger", *action.Trigger) + case insights.LogToMetricAction: + d.Set("action_type", "LogToMetric") + d.Set("criteria", *action.Criteria) + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", *schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", *schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", *source.AuthorizedResources) + } + if source.DataSourceID != nil { + d.Set("data_source_id", *source.DataSourceID) + } + if source.Query != nil { + d.Set("query", *source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + // read-only props + d.Set("last_updated_time", *resp.LastUpdatedTime) + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/data_source_monitor_scheduled_query_rules_test.go b/azurerm/data_source_monitor_scheduled_query_rules_test.go new file mode 100644 index 000000000000..5aed5d979732 --- /dev/null +++ b/azurerm/data_source_monitor_scheduled_query_rules_test.go @@ -0,0 +1,243 @@ +package azurerm + +import ( + "fmt" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { + dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(10) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttr(dataSourceName, "enabled", "true"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { + dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(10) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "id"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { + dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(10) + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "id"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_percent Idle Time" + dimension { + name = "dimension" + operator = "Include" + values = ["latency"] + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt, rInt) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(rInt int, rString string, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestSqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt, rInt, ts, ts) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(rInt int, rString string, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_log_analytics_workspace" "test2" { + name = "acctestWorkspace2-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestSqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +} diff --git a/azurerm/internal/services/monitor/client.go b/azurerm/internal/services/monitor/client.go index accb35d792cd..137284ec756c 100644 --- a/azurerm/internal/services/monitor/client.go +++ b/azurerm/internal/services/monitor/client.go @@ -17,6 +17,7 @@ type Client struct { DiagnosticSettingsCategoryClient *insights.DiagnosticSettingsCategoryClient LogProfilesClient *insights.LogProfilesClient MetricAlertsClient *insights.MetricAlertsClient + ScheduledQueryRulesClient *insights.ScheduledQueryRulesClient } func BuildClient(o *common.ClientOptions) *Client { @@ -44,6 +45,9 @@ func BuildClient(o *common.ClientOptions) *Client { MetricAlertsClient := insights.NewMetricAlertsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&MetricAlertsClient.Client, o.ResourceManagerAuthorizer) + ScheduledQueryRulesClient := insights.NewScheduledQueryRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&ScheduledQueryRulesClient.Client, o.ResourceManagerAuthorizer) + return &Client{ AutoscaleSettingsClient: &AutoscaleSettingsClient, ActionGroupsClient: &ActionGroupsClient, @@ -53,5 +57,6 @@ func BuildClient(o *common.ClientOptions) *Client { DiagnosticSettingsCategoryClient: &DiagnosticSettingsCategoryClient, LogProfilesClient: &LogProfilesClient, MetricAlertsClient: &MetricAlertsClient, + ScheduledQueryRulesClient: &ScheduledQueryRulesClient, } } diff --git a/azurerm/provider.go b/azurerm/provider.go index 535d670e026c..e28a2929189d 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -106,6 +106,7 @@ func Provider() terraform.ResourceProvider { "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules": dataSourceArmMonitorScheduledQueryRules(), "azurerm_mssql_elasticpool": dataSourceArmMsSqlElasticpool(), "azurerm_netapp_account": dataSourceArmNetAppAccount(), "azurerm_netapp_pool": dataSourceArmNetAppPool(), @@ -361,6 +362,7 @@ func Provider() terraform.ResourceProvider { "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules": resourceArmMonitorScheduledQueryRules(), "azurerm_mssql_elasticpool": resourceArmMsSqlElasticPool(), "azurerm_mysql_configuration": resourceArmMySQLConfiguration(), "azurerm_mysql_database": resourceArmMySqlDatabase(), diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go new file mode 100644 index 000000000000..ab85d9837572 --- /dev/null +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -0,0 +1,685 @@ +package azurerm + +import ( + "fmt" + "log" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRules() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMonitorScheduledQueryRulesCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesRead, + Update: resourceArmMonitorScheduledQueryRulesCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "action_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Alerting", + "LogToMetric", + }, false), + }, + "authorized_resources": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Optional: true, + Default: "{}", + ValidateFunc: validation.ValidateJsonString, + }, + "email_subject": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Include", + }, false), + }, + "values": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "frequency": { + Type: schema.TypeInt, + Optional: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + }, + "query_type": { + Type: schema.TypeString, + Optional: true, + Default: "ResultCount", + ValidateFunc: validation.StringInSlice([]string{ + "ResultCount", + }, false), + }, + "severity": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{ + 0, + 1, + 2, + 3, + 4, + }), + }, + "throttling": { + Type: schema.TypeInt, + Optional: true, + }, + "time_window": { + Type: schema.TypeInt, + Optional: true, + }, + "trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Required: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Consecutive", + "Total", + }, false), + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules", *existing.ID) + } + } + + actionType := d.Get("action_type").(string) + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if enabledRaw == false { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + var action insights.BasicAction + switch actionType { + case "Alerting": + action = expandMonitorScheduledQueryRulesAlertingAction(d) + case "LogToMetric": + action = expandMonitorScheduledQueryRulesLogToMetricAction(d) + default: + return fmt.Errorf("Invalid action_type %q. Value must be either 'Alerting' or 'LogToMetric'", actionType) + } + + source := expandMonitorScheduledQueryRulesSource(d) + schedule := expandMonitorScheduledQueryRulesSchedule(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", *resp.Description) + + switch action := resp.Action.(type) { + case insights.AlertingAction: + d.Set("action_type", "Alerting") + d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)) + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", *action.ThrottlingInMin) + d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) + case insights.LogToMetricAction: + d.Set("action_type", "LogToMetric") + d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", *schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", *schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", *source.AuthorizedResources) + } + if source.DataSourceID != nil { + d.Set("data_source_id", *source.DataSourceID) + } + if source.Query != nil { + d.Set("query", *source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + // read-only props + d.Set("last_updated_time", *resp.LastUpdatedTime) + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { + aznsActionRaw := d.Get("azns_action").(*schema.Set).List() + aznsAction := expandMonitorScheduledQueryRulesAznsAction(aznsActionRaw) + severityRaw := d.Get("severity").(int) + severity := strconv.Itoa(severityRaw) + throttling := d.Get("throttling").(int) + + triggerRaw := d.Get("trigger").(*schema.Set).List() + trigger := expandMonitorScheduledQueryRulesTrigger(triggerRaw) + + action := insights.AlertingAction{ + AznsAction: aznsAction, + Severity: insights.AlertSeverity(severity), + ThrottlingInMin: utils.Int32(int32(throttling)), + Trigger: trigger, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesAlertingAction, + } + + return &action +} + +func expandMonitorScheduledQueryRulesAznsAction(input []interface{}) *insights.AzNsActionGroup { + result := insights.AzNsActionGroup{} + + for _, item := range input { + v := item.(map[string]interface{}) + actionGroups := v["action_group"].(*schema.Set).List() + + result.ActionGroup = utils.ExpandStringSlice(actionGroups) + result.EmailSubject = utils.String(v["email_subject"].(string)) + result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesCriteria(input []interface{}) *[]insights.Criteria { + criteria := make([]insights.Criteria, 0) + for _, item := range input { + v := item.(map[string]interface{}) + + dimensions := make([]insights.Dimension, 0) + for _, dimension := range v["dimension"].(*schema.Set).List() { + dVal := dimension.(map[string]interface{}) + dimensions = append(dimensions, insights.Dimension{ + Name: utils.String(dVal["name"].(string)), + Operator: utils.String(dVal["operator"].(string)), + Values: utils.ExpandStringSlice(dVal["values"].([]interface{})), + }) + } + + criteria = append(criteria, insights.Criteria{ + MetricName: utils.String(v["metric_name"].(string)), + Dimensions: &dimensions, + }) + } + return &criteria +} + +func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { + criteriaRaw := d.Get("criteria").(*schema.Set).List() + criteria := expandMonitorScheduledQueryRulesCriteria(criteriaRaw) + + action := insights.LogToMetricAction{ + Criteria: criteria, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesLogToMetricAction, + } + + return &action +} + +func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights.Schedule { + frequency := d.Get("frequency").(int) + timeWindow := d.Get("time_window").(int) + + schedule := insights.Schedule{ + FrequencyInMinutes: utils.Int32(int32(frequency)), + TimeWindowInMinutes: utils.Int32(int32(timeWindow)), + } + + return &schedule +} + +func expandMonitorScheduledQueryRulesMetricTrigger(input []interface{}) *insights.LogMetricTrigger { + result := insights.LogMetricTrigger{} + + for _, item := range input { + v := item.(map[string]interface{}) + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) + result.MetricColumn = utils.String(v["metric_column"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { + authorizedResources := d.Get("authorized_resources").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query := d.Get("query").(string) + + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResources), + DataSourceID: utils.String(dataSourceID), + Query: utils.String(query), + QueryType: insights.ResultCount, + } + + return &source +} + +func expandMonitorScheduledQueryRulesTrigger(input []interface{}) *insights.TriggerCondition { + result := insights.TriggerCondition{} + + for _, item := range input { + v := item.(map[string]interface{}) + metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() + + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTrigger = expandMonitorScheduledQueryRulesMetricTrigger(metricTriggerRaw) + } + + return &result +} + +func flattenAzureRmScheduledQueryRulesAznsAction(input *insights.AzNsActionGroup) []interface{} { + result := make([]interface{}, 0) + v := make(map[string]interface{}) + + if input != nil { + if input.ActionGroup != nil { + v["action_group"] = *input.ActionGroup + } + v["email_subject"] = input.EmailSubject + v["custom_webhook_payload"] = input.CustomWebhookPayload + } + result = append(result, v) + + return result +} + +func flattenAzureRmScheduledQueryRulesCriteria(input *[]insights.Criteria) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, criteria := range *input { + v := make(map[string]interface{}) + + /*if err = d.Set("azure_function_receiver", flattenMonitorActionGroupAzureFunctionReceiver(group.AzureFunctionReceivers)); err != nil { + return fmt.Errorf("Error setting `azure_function_receiver`: %+v", err) + }*/ + v["dimension"] = flattenAzureRmScheduledQueryRulesDimension(criteria.Dimensions) + v["metric_name"] = *criteria.MetricName + + result = append(result, v) + } + } + + return result +} + +func flattenAzureRmScheduledQueryRulesDimension(input *[]insights.Dimension) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, dimension := range *input { + v := make(map[string]interface{}) + + if dimension.Name != nil { + v["name"] = *dimension.Name + } + + if dimension.Operator != nil { + v["operator"] = *dimension.Operator + } + + if dimension.Values != nil { + v["values"] = *dimension.Values + } + + result = append(result, v) + } + } + + return result +} + +func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTrigger) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + result["metric_trigger_type"] = string(input.MetricTriggerType) + + if input.MetricColumn != nil { + result["metric_column"] = *input.MetricColumn + } + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesSchedule(input *insights.Schedule) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + if input.FrequencyInMinutes != nil { + result["frequency_in_minutes"] = int(*input.FrequencyInMinutes) + } + + if input.TimeWindowInMinutes != nil { + result["time_window_in_minutes"] = int(*input.TimeWindowInMinutes) + } + + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesSource(input *insights.Source) []interface{} { + result := make(map[string]interface{}) + + if input.AuthorizedResources != nil { + result["authorized_resources"] = *input.AuthorizedResources + } + if input.DataSourceID != nil { + result["data_source_id"] = *input.DataSourceID + } + if input.Query != nil { + result["query"] = *input.Query + } + result["query_type"] = string(input.QueryType) + + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) []interface{} { + result := make(map[string]interface{}) + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + if input.MetricTrigger != nil { + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesMetricTrigger(input.MetricTrigger) + } + + return []interface{}{result} +} diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go new file mode 100644 index 000000000000..fa371118723f --- /dev/null +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -0,0 +1,320 @@ +package azurerm + +import ( + "fmt" + "net/http" + "strings" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" +) + +func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { + resourceName := "azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := strings.ToLower(acctest.RandString(11)) + location := testLocation() + config := testAccAzureRMMonitorScheduledQueryRules_alertingAction(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + return +} + +func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { + resourceName := "azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := strings.ToLower(acctest.RandString(11)) + location := testLocation() + config := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + return +} + +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { + resourceName := "azurerm_monitor_scheduled_query_rules.test" + ri := tf.AccRandTimeInt() + rs := strings.ToLower(acctest.RandString(11)) + location := testLocation() + config := testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(ri, rs, location) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + return +} + +func testAccAzureRMMonitorScheduledQueryRules_alertingAction(rInt int, rString, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "Alerting" + + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + custom_webhook_payload = "{}" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 5 + metric_trigger_type = "Consecutive" + metric_column = "Computer" + } + } +} +`, rInt, location, rInt, rInt, rInt, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(rInt int, rString, location string) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "Alerting" + + authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 5 + metric_trigger_type = "Consecutive" + metric_column = "Computer" + } + } +} +`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(rInt int, rString, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_percent Idle Time" + dimension { + name = "dimension" + operator = "Include" + values = ["latency"] + } + } +} +`, rInt, location, rInt, rInt, rInt) +} + +func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_monitor_scheduled_query_rules" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(ctx, resourceGroup, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + } + } + + return nil +} + +func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Activity Log Alert Instance: %s", name) + } + + conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("Bad: Get on monitorScheduledQueryRulesClient: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} diff --git a/website/docs/d/monitor_scheduled_query_rules.html.markdown b/website/docs/d/monitor_scheduled_query_rules.html.markdown new file mode 100644 index 000000000000..804ec3e2606c --- /dev/null +++ b/website/docs/d/monitor_scheduled_query_rules.html.markdown @@ -0,0 +1,88 @@ +--- +subcategory: "" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules" +description: |- + Get information about the specified Scheduled Query Rule. +--- + +# Data Source: azurerm_monitor_scheduled_query_rules + +Use this data source to access the properties of a Scheduled Query Rule. + +## Example Usage + +```hcl +data "azurerm_monitor_scheduled_query_rules" "example" { + resource_group_name = "terraform-example-rg" + name = "tfex-queryrule" +} + +output "query_rule_id" { + value = "${data.azurerm_monitor_scheduled_query_rules.example.id}" +} +``` + +## Argument Reference + +* `name` - (Required) Specifies the name of the Scheduled Query Rule. +* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. + +## Attributes Reference + +* `id` - The ID of the Scheduled Query Rule. +* `azns_action` - An `azns_action` block as defined below. +* `action_type` - Must equal ether `AlertingAction` or `LogToMetricAction`. +* `authorized_resources` - List of Resource IDs referred into query. +* `criteria` - A `criteria` block as defined below. +* `data_source_id` - The resource uri over which log search query is to be run. +* `description` - The description of the Scheduled Query Rule. +* `enabled` - Whether this scheduled query rule is enabled. +* `frequency` - Frequency (in minutes) at which rule condition should be evaluated. +* `query` - Log search query. Required for action type - `alerting_action`. +* `query_type` - Must equal "ResultCount". +* `time_window` - Time window for which data needs to be fetched for query (should be greater than or equal to frequency_in_minutes). +* `severity` - Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. +* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. +* `trigger` - A `trigger` block as defined below. The condition that results in the alert rule being run. + +--- + +* `azns_action` supports the following: + +* `action_group` - (Optional) List of action group reference resource IDs. +* `custom_webhook_payload` - Custom payload to be sent for all webhook URI in Azure action group. +* `email_subject` - Custom subject override for all email ids in Azure action group. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. + +--- + +`metricTrigger` supports the following: + +* `metricColumn` - (Required) Evaluation of metric on a particular column. +* `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) The threshold of the metric trigger. + +--- + +`trigger` supports the following: + +* `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) Result or count threshold based on which rule should be triggered. diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules.html.markdown new file mode 100644 index 000000000000..439981bc06a5 --- /dev/null +++ b/website/docs/r/monitor_scheduled_query_rules.html.markdown @@ -0,0 +1,193 @@ +--- +subcategory: "Monitor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules" +description: |- + Manages a Scheduled Query Rule within Azure Monitor +--- + +# azurerm_monitor_action_group + +Manages a Scheduled Query Rule within Azure Monitor. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "monitoring-resources" + location = "West US" +} + +resource "azurerm_application_insights" "example" { + name = "appinsights" + location = var.location + resource_group_name = azurerm_resource_group.example.name + application_type = "web" +} + +resource "azurerm_log_analytics_workspace" "example" { + name = "loganalytics" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku = "PerGB2018" + retention_in_days = 30 +} + +# Example: AlertingAction +resource "azurerm_scheduled_query_rule" "example" { + name = format("%s-queryrule", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action_type = "AlertingAction" + azns_action = { + action_group = [] + email_subject = "Email Header" + custom_webhook_payload = {} + } + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule AlertingAction example" + enabled = true + frequency = 5 + query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + query_type = "ResultCount" + severity = "1" + time_window = 30 + trigger = { + threshold_operator = "GreaterThan" + threshold = 3 + } +} + +# Example: AlertingAction Cross-Resource +resource "azurerm_scheduled_query_rule" "example2" { + name = format("%s-queryrule2", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action_type = "AlertingAction" + authorized_resources = [azurerm_application_insights.example.id, + azurerm_log_analytics_workspace.example.id] + azns_action = { + action_group = [] + email_subject = "Email Header" + custom_webhook_payload = {} + } + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule AlertingAction cross-resource example" + enabled = true + frequency = 5 + query = "union requests, workspace(\"loganalytics\").Heartbeat" + query_type = "ResultCount" + severity = "1" + time_window = 30 + trigger = { + threshold_operator = "GreaterThan" + threshold = 3 + } +} + +# Example: LogToMetricAction +resource "azurerm_scheduled_query_rule" "example3" { + name = format("%s-queryrule3", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action_type = "LogToMetricAction" + criteria = [{ + metric_name = "Average_% Idle Time" + dimensions = [{ + name = "dimension" + operator = "GreaterThan" + values = ["latency"] + }] + }] + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule LogToMetric example" + enabled = true +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `action_type` - (Required) Must equal ether `AlertingAction` or `LogToMetricAction`. +* `authorized_resources` - (Optional) List of Resource IDs referred into query. +* `data_source_id` - (Required) The resource uri over which log search query is to be run. +* `description` - (Optional) The description of the Scheduled Query Rule. +* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. + +The following arguments are only supported when `action_type` is `AlertingAction`: + +* `azns_action` - (Optional) An `azns_action` block as defined below. +* `frequency` - (Optional) Frequency (in minutes) at which rule condition should be evaluated. Required when `action_type` is `AlertingAction`. +* `query` - (Optional) Log search query. Required when `action_type` is `AlertingAction`. +* `query_type` - (Optional) Must equal "ResultCount" for now. Required when `action_type` is `AlertingAction`. +* `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. +* `time_window` - (Optional) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). Required when `action_type` is `AlertingAction`. +* `trigger` - (Optional) The condition that results in the alert rule being run. Required when `action_type` is `AlertingAction`. + +The following arguments are only supported when `action_type` is `LogToMetricAction`: + +* `criteria` - (Optional) A `criteria` block as defined below. Required when `action_type` is `LogToMetricAction`. + +--- + +* `azns_action` supports the following: + +* `action_group` - (Optional) List of action group reference resource IDs. +* `custom_webhook_payload` - (Optional) Custom payload to be sent for all webhook payloads in alerting action. +* `email_subject` - (Optional) Custom subject override for all email ids in Azure action group. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. + +--- + +`metricTrigger` supports the following: + +* `metricColumn` - (Required) Evaluation of metric on a particular column. +* `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) The threshold of the metric trigger. + +--- + +`trigger` supports the following: + +* `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. +* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - (Required) Result or count threshold based on which rule should be triggered. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Scheduled Query Rule. +* `last_updated_time` - Last time the rule was updated in IS08601 format. +* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' + +## Import + +Scheduled Query Rules can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_monitor_scheduled_query_rules.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +``` From 5303ecd0bc242d24e1d3d46dd52238105950ef0c Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:25:12 -0600 Subject: [PATCH 02/25] Acceptance tests passing --- ...ta_source_monitor_scheduled_query_rules.go | 19 ++++++++----- ...urce_monitor_scheduled_query_rules_test.go | 27 ++++++++++++++----- ...ource_arm_monitor_scheduled_query_rules.go | 10 +++---- ..._arm_monitor_scheduled_query_rules_test.go | 24 ++++++++--------- 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go index 7d551ed10437..5d9c5bbbadb6 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -85,8 +85,11 @@ func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { Computed: true, }, "values": { - Type: schema.TypeString, + Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, }, }, }, @@ -220,17 +223,20 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in switch action := resp.Action.(type) { case insights.AlertingAction: d.Set("action_type", "Alerting") - d.Set("azns_action", *action.AznsAction) + + aznsAction := flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction) + d.Set("azns_action", aznsAction) + severity, err := strconv.Atoi(string(action.Severity)) if err != nil { return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) } d.Set("severity", severity) d.Set("throttling", *action.ThrottlingInMin) - d.Set("trigger", *action.Trigger) + d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) case insights.LogToMetricAction: d.Set("action_type", "LogToMetric") - d.Set("criteria", *action.Criteria) + d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } @@ -257,8 +263,9 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in d.Set("query_type", string(source.QueryType)) } - // read-only props - d.Set("last_updated_time", *resp.LastUpdatedTime) + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", *lastUpdated) + } d.Set("provisioning_state", resp.ProvisioningState) return tags.FlattenAndSet(d, resp.Tags) diff --git a/azurerm/data_source_monitor_scheduled_query_rules_test.go b/azurerm/data_source_monitor_scheduled_query_rules_test.go index 5aed5d979732..2642ac2652a9 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules_test.go +++ b/azurerm/data_source_monitor_scheduled_query_rules_test.go @@ -15,16 +15,16 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes ri := tf.AccRandTimeInt() rs := acctest.RandString(10) location := testLocation() + config := testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location), + Config: config, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "id"), - resource.TestCheckResourceAttr(dataSourceName, "enabled", "true"), ), }, }, @@ -36,13 +36,14 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin ri := tf.AccRandTimeInt() rs := acctest.RandString(10) location := testLocation() + config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location), + Config: config, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "id"), ), @@ -56,13 +57,14 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou ri := tf.AccRandTimeInt() rs := acctest.RandString(10) location := testLocation() + config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location), + Config: config, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(dataSourceName, "id"), ), @@ -142,21 +144,20 @@ resource "azurerm_monitor_action_group" "test" { } resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestSqr-%d" + name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true action_type = "Alerting" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" data_source_id = "${azurerm_log_analytics_workspace.test.id}" query_type = "ResultCount" frequency = 60 time_window = 60 - severity = 3 azns_action { action_group = ["${azurerm_monitor_action_group.test.id}"] @@ -166,6 +167,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { trigger { operator = "GreaterThan" threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } } } @@ -232,6 +239,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { trigger { operator = "GreaterThan" threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } } } diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index ab85d9837572..650cd33b995b 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -346,6 +346,10 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) } + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", *lastUpdated) + } + d.Set("provisioning_state", resp.ProvisioningState) if resp.Enabled == insights.True { d.Set("enabled", true) @@ -395,17 +399,13 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte d.Set("query_type", string(source.QueryType)) } - // read-only props - d.Set("last_updated_time", *resp.LastUpdatedTime) - d.Set("provisioning_state", resp.ProvisioningState) - return tags.FlattenAndSet(d, resp.Tags) } func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) - defer cancel() + defer cancel() id, err := azure.ParseAzureResourceID(d.Id()) if err != nil { diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go index fa371118723f..7d7c2d2fdce1 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -123,12 +123,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" + description = "test alerting action" enabled = true action_type = "Alerting" data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" query_type = "ResultCount" frequency = 60 @@ -142,13 +142,13 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } trigger { - operator = "GreaterThan" - threshold = 5000 + operator = "GreaterThan" + threshold = 5000 metric_trigger { operator = "GreaterThan" - threshold = 5 - metric_trigger_type = "Consecutive" - metric_column = "Computer" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" } } } @@ -189,13 +189,13 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" + description = "test alerting action cross-resource" enabled = true action_type = "Alerting" authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" query_type = "ResultCount" frequency = 60 @@ -212,9 +212,9 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { threshold = 5000 metric_trigger { operator = "GreaterThan" - threshold = 5 - metric_trigger_type = "Consecutive" - metric_column = "Computer" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" } } } From 607a00d86b40fbb0f92c9e384851ff86caaa6d54 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 3 Dec 2019 09:19:32 -0600 Subject: [PATCH 03/25] Fix linting errors; minor cleanup --- ...ta_source_monitor_scheduled_query_rules.go | 31 ++++---- ...ource_arm_monitor_scheduled_query_rules.go | 75 ++++--------------- ..._arm_monitor_scheduled_query_rules_test.go | 3 - 3 files changed, 32 insertions(+), 77 deletions(-) diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go index 5d9c5bbbadb6..6e12d2426648 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -213,7 +213,7 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in d.Set("location", azure.NormalizeLocation(*location)) } - d.Set("description", *resp.Description) + d.Set("description", resp.Description) if resp.Enabled == insights.True { d.Set("enabled", true) } else { @@ -223,48 +223,51 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in switch action := resp.Action.(type) { case insights.AlertingAction: d.Set("action_type", "Alerting") - - aznsAction := flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction) - d.Set("azns_action", aznsAction) - + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `azns_action`: %+v", err) + } severity, err := strconv.Atoi(string(action.Severity)) if err != nil { return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) } d.Set("severity", severity) - d.Set("throttling", *action.ThrottlingInMin) - d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } case insights.LogToMetricAction: d.Set("action_type", "LogToMetric") - d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } if schedule := resp.Schedule; schedule != nil { if schedule.FrequencyInMinutes != nil { - d.Set("frequency", *schedule.FrequencyInMinutes) + d.Set("frequency", schedule.FrequencyInMinutes) } if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", *schedule.TimeWindowInMinutes) + d.Set("time_window", schedule.TimeWindowInMinutes) } } if source := resp.Source; source != nil { if source.AuthorizedResources != nil { - d.Set("authorized_resources", *source.AuthorizedResources) + d.Set("authorized_resources", source.AuthorizedResources) } if source.DataSourceID != nil { - d.Set("data_source_id", *source.DataSourceID) + d.Set("data_source_id", source.DataSourceID) } if source.Query != nil { - d.Set("query", *source.Query) + d.Set("query", source.Query) } d.Set("query_type", string(source.QueryType)) } if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", *lastUpdated) + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) } d.Set("provisioning_state", resp.ProvisioningState) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index 650cd33b995b..0f9d720f31a9 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -269,7 +269,7 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m enabledRaw := d.Get("enabled").(bool) enabled := insights.True - if enabledRaw == false { + if !enabledRaw { enabled = insights.False } @@ -347,7 +347,7 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte d.Set("location", azure.NormalizeLocation(*location)) } if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", *lastUpdated) + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) } d.Set("provisioning_state", resp.ProvisioningState) @@ -357,46 +357,39 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte d.Set("enabled", false) } - d.Set("description", *resp.Description) + d.Set("description", resp.Description) switch action := resp.Action.(type) { case insights.AlertingAction: d.Set("action_type", "Alerting") - d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)) + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `azns_action`: %+v", err) + } severity, err := strconv.Atoi(string(action.Severity)) if err != nil { return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) } d.Set("severity", severity) - d.Set("throttling", *action.ThrottlingInMin) - d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } case insights.LogToMetricAction: d.Set("action_type", "LogToMetric") - d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)) + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } if schedule := resp.Schedule; schedule != nil { if schedule.FrequencyInMinutes != nil { - d.Set("frequency", *schedule.FrequencyInMinutes) + d.Set("frequency", schedule.FrequencyInMinutes) } if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", *schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", *source.AuthorizedResources) - } - if source.DataSourceID != nil { - d.Set("data_source_id", *source.DataSourceID) - } - if source.Query != nil { - d.Set("query", *source.Query) + d.Set("time_window", schedule.TimeWindowInMinutes) } - d.Set("query_type", string(source.QueryType)) } return tags.FlattenAndSet(d, resp.Tags) @@ -573,9 +566,6 @@ func flattenAzureRmScheduledQueryRulesCriteria(input *[]insights.Criteria) []int for _, criteria := range *input { v := make(map[string]interface{}) - /*if err = d.Set("azure_function_receiver", flattenMonitorActionGroupAzureFunctionReceiver(group.AzureFunctionReceivers)); err != nil { - return fmt.Errorf("Error setting `azure_function_receiver`: %+v", err) - }*/ v["dimension"] = flattenAzureRmScheduledQueryRulesDimension(criteria.Dimensions) v["metric_name"] = *criteria.MetricName @@ -633,41 +623,6 @@ func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTri return []interface{}{result} } -func flattenAzureRmScheduledQueryRulesSchedule(input *insights.Schedule) []interface{} { - result := make(map[string]interface{}) - - if input == nil { - return []interface{}{} - } - - if input.FrequencyInMinutes != nil { - result["frequency_in_minutes"] = int(*input.FrequencyInMinutes) - } - - if input.TimeWindowInMinutes != nil { - result["time_window_in_minutes"] = int(*input.TimeWindowInMinutes) - } - - return []interface{}{result} -} - -func flattenAzureRmScheduledQueryRulesSource(input *insights.Source) []interface{} { - result := make(map[string]interface{}) - - if input.AuthorizedResources != nil { - result["authorized_resources"] = *input.AuthorizedResources - } - if input.DataSourceID != nil { - result["data_source_id"] = *input.DataSourceID - } - if input.Query != nil { - result["query"] = *input.Query - } - result["query_type"] = string(input.QueryType) - - return []interface{}{result} -} - func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) []interface{} { result := make(map[string]interface{}) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go index 7d7c2d2fdce1..b426231b251c 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -38,7 +38,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { }, }, }) - return } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { @@ -66,7 +65,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }, }, }) - return } func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { @@ -94,7 +92,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { }, }, }) - return } func testAccAzureRMMonitorScheduledQueryRules_alertingAction(rInt int, rString, location string) string { From ebf84e9fa0ea474bb2d330c73977fa5d43315f4a Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:19:21 -0600 Subject: [PATCH 04/25] Minor updates and bug fixes - Fix some sprintf formatting - Improve documentation for cross-resource query - Don't create an empty metric_trigger {} if user doesn't specify block --- ...ta_source_monitor_scheduled_query_rules.go | 2 +- ...urce_monitor_scheduled_query_rules_test.go | 6 +- ...ource_arm_monitor_scheduled_query_rules.go | 23 +++++++- ..._arm_monitor_scheduled_query_rules_test.go | 24 +++----- ...onitor_scheduled_query_rules.html.markdown | 57 +++++++++++-------- 5 files changed, 66 insertions(+), 46 deletions(-) diff --git a/azurerm/data_source_monitor_scheduled_query_rules.go b/azurerm/data_source_monitor_scheduled_query_rules.go index 6e12d2426648..6f74ed992cf9 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/data_source_monitor_scheduled_query_rules.go @@ -255,7 +255,7 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in if source := resp.Source; source != nil { if source.AuthorizedResources != nil { - d.Set("authorized_resources", source.AuthorizedResources) + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) } if source.DataSourceID != nil { d.Set("data_source_id", source.DataSourceID) diff --git a/azurerm/data_source_monitor_scheduled_query_rules_test.go b/azurerm/data_source_monitor_scheduled_query_rules_test.go index 2642ac2652a9..b8090d408463 100644 --- a/azurerm/data_source_monitor_scheduled_query_rules_test.go +++ b/azurerm/data_source_monitor_scheduled_query_rules_test.go @@ -104,11 +104,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { data_source_id = "${azurerm_application_insights.test.id}" criteria { - metric_name = "Average_percent Idle Time" + metric_name = "Average_%% Idle Time" dimension { - name = "dimension" + name = "InstanceName" operator = "Include" - values = ["latency"] + values = [""] } } } diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index 0f9d720f31a9..a3e2e48dd468 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -215,8 +215,9 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { }, false), }, "threshold": { - Type: schema.TypeFloat, - Required: true, + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.NoZeroValues, }, }, }, @@ -392,6 +393,19 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte } } + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + return tags.FlattenAndSet(d, resp.Tags) } @@ -500,8 +514,11 @@ func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights. } func expandMonitorScheduledQueryRulesMetricTrigger(input []interface{}) *insights.LogMetricTrigger { - result := insights.LogMetricTrigger{} + if len(input) == 0 { + return nil + } + result := insights.LogMetricTrigger{} for _, item := range input { v := item.(map[string]interface{}) result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go index b426231b251c..e5de80da1288 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules_test.go @@ -153,8 +153,6 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(rInt int, rString, location string) string { - ts := time.Now().Format(time.RFC3339) - return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -192,11 +190,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) query_type = "ResultCount" frequency = 60 - time_window = 60 + time_window = 60 severity = 3 azns_action { @@ -205,17 +203,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } + operator = "GreaterThan" + threshold = 5000 } } -`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +`, rInt, location, rInt, rInt, rInt, rInt) } func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(rInt int, rString, location string) string { @@ -249,11 +241,11 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { data_source_id = "${azurerm_application_insights.test.id}" criteria { - metric_name = "Average_percent Idle Time" + metric_name = "Average_%% Idle Time" dimension { - name = "dimension" + name = "InstanceName" operator = "Include" - values = ["latency"] + values = [""] } } } diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules.html.markdown index 439981bc06a5..dfcb7279a4f7 100644 --- a/website/docs/r/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules.html.markdown @@ -34,75 +34,86 @@ resource "azurerm_log_analytics_workspace" "example" { retention_in_days = 30 } -# Example: AlertingAction +# Example: Alerting Action resource "azurerm_scheduled_query_rule" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "AlertingAction" - azns_action = { + action_type = "Alerting" + azns_action { action_group = [] email_subject = "Email Header" - custom_webhook_payload = {} + custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule AlertingAction example" + description = "Scheduled query rule Alerting Action example" enabled = true frequency = 5 query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" query_type = "ResultCount" - severity = "1" + severity = 1 time_window = 30 - trigger = { + trigger { threshold_operator = "GreaterThan" threshold = 3 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "timestamp" + } } } -# Example: AlertingAction Cross-Resource +# Example: Alerting Action Cross-Resource resource "azurerm_scheduled_query_rule" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "AlertingAction" + action_type = "Alerting" authorized_resources = [azurerm_application_insights.example.id, azurerm_log_analytics_workspace.example.id] - azns_action = { + azns_action { action_group = [] email_subject = "Email Header" - custom_webhook_payload = {} + custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule AlertingAction cross-resource example" + description = "Scheduled query rule Alerting Action cross-resource example" enabled = true frequency = 5 - query = "union requests, workspace(\"loganalytics\").Heartbeat" + query = format(< ago(1h) | where ObjectName == "Processor" and CounterName == "%% Processor Time" | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); +let b=requests | where resultCode == "200" and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); +a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5 +QUERY + , azurerm_log_analytics_workspace.example.id) query_type = "ResultCount" severity = "1" time_window = 30 - trigger = { + trigger { threshold_operator = "GreaterThan" threshold = 3 } } -# Example: LogToMetricAction +# Example: LogToMetric Action resource "azurerm_scheduled_query_rule" "example3" { name = format("%s-queryrule3", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "LogToMetricAction" - criteria = [{ + action_type = "LogToMetric" + criteria { metric_name = "Average_% Idle Time" - dimensions = [{ - name = "dimension" - operator = "GreaterThan" - values = ["latency"] - }] - }] + dimensions { + name = "InstanceName" + operator = "Include" + values = [""] + } + } data_source_id = azurerm_application_insights.example.id description = "Scheduled query rule LogToMetric example" enabled = true From ce59b1af4f98d5a74d502539dd5dfef135d04b91 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Thu, 5 Dec 2019 13:26:08 -0600 Subject: [PATCH 05/25] Remove heredoc in docs example --- website/docs/r/monitor_scheduled_query_rules.html.markdown | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules.html.markdown index dfcb7279a4f7..8d18bebe2327 100644 --- a/website/docs/r/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules.html.markdown @@ -84,12 +84,7 @@ resource "azurerm_scheduled_query_rule" "example2" { description = "Scheduled query rule Alerting Action cross-resource example" enabled = true frequency = 5 - query = format(< ago(1h) | where ObjectName == "Processor" and CounterName == "%% Processor Time" | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); -let b=requests | where resultCode == "200" and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); -a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5 -QUERY - , azurerm_log_analytics_workspace.example.id) + query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) query_type = "ResultCount" severity = "1" time_window = 30 From a1bf9bacb68a0699b66722cc605236f07ca81f0a Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Wed, 11 Dec 2019 01:35:23 -0600 Subject: [PATCH 06/25] fix response import --- azurerm/resource_arm_monitor_scheduled_query_rules.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_monitor_scheduled_query_rules.go b/azurerm/resource_arm_monitor_scheduled_query_rules.go index a3e2e48dd468..0a6e2ff31cac 100644 --- a/azurerm/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/resource_arm_monitor_scheduled_query_rules.go @@ -7,10 +7,10 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" From 8acb500d31c30f5af44d694a9c250a440e9c7534 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Fri, 27 Dec 2019 17:51:08 -0600 Subject: [PATCH 07/25] Update tests and docs to pass checks --- ...urce_monitor_scheduled_query_rules_test.go | 60 ++++++-------- ..._arm_monitor_scheduled_query_rules_test.go | 79 ++++++++----------- ...onitor_scheduled_query_rules.html.markdown | 2 +- 3 files changed, 57 insertions(+), 84 deletions(-) rename azurerm/internal/services/monitor/{ => tests}/data_source_monitor_scheduled_query_rules_test.go (78%) rename azurerm/internal/services/monitor/{ => tests}/resource_arm_monitor_scheduled_query_rules_test.go (77%) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go similarity index 78% rename from azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go index 089835482e1e..875fdaa76202 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go @@ -1,31 +1,25 @@ -package monitor +package tests import ( "fmt" "testing" "time" - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { - dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(10) - location := testLocation() - config := testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(ri, rs, location) + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: config, + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), }, }, @@ -33,20 +27,16 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes } func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { - dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(10) - location := testLocation() - config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(ri, rs, location) + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: config, + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), }, }, @@ -54,27 +44,23 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin } func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { - dataSourceName := "data.azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := acctest.RandString(10) - location := testLocation() - config := testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(ri, rs, location) + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: config, + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(dataSourceName, "id"), + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), }, }, }) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(rInt int, rString string, location string) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -118,10 +104,10 @@ data "azurerm_monitor_scheduled_query_rules" "test" { name = "${azurerm_monitor_scheduled_query_rules.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } -`, rInt, location, rInt, rInt, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(rInt int, rString string, location string) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -181,10 +167,10 @@ data "azurerm_monitor_scheduled_query_rules" "test" { name = "${azurerm_monitor_scheduled_query_rules.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } -`, rInt, location, rInt, rInt, rInt, ts, ts) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(rInt int, rString string, location string) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -253,5 +239,5 @@ data "azurerm_monitor_scheduled_query_rules" "test" { name = "${azurerm_monitor_scheduled_query_rules.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } -`, rInt, location, rInt, rInt, rInt, rInt, ts, ts) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go similarity index 77% rename from azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go index 559bcacf3b43..357a8ba2b0f9 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go @@ -1,38 +1,33 @@ -package monitor +package tests import ( "fmt" "net/http" - "strings" "testing" "time" - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { - resourceName := "azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := strings.ToLower(acctest.RandString(11)) - location := testLocation() - config := testAccAzureRMMonitorScheduledQueryRules_alertingAction(ri, rs, location) + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMMonitorScheduledQueryRules_alertingAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -41,25 +36,21 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { - resourceName := "azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := strings.ToLower(acctest.RandString(11)) - location := testLocation() - config := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(ri, rs, location) + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -68,25 +59,21 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes } func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { - resourceName := "azurerm_monitor_scheduled_query_rules.test" - ri := tf.AccRandTimeInt() - rs := strings.ToLower(acctest.RandString(11)) - location := testLocation() - config := testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(ri, rs, location) + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, Steps: []resource.TestStep{ { - Config: config, + Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName), + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), ), }, { - ResourceName: resourceName, + ResourceName: data.ResourceName, ImportState: true, ImportStateVerify: true, }, @@ -94,7 +81,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { }) } -func testAccAzureRMMonitorScheduledQueryRules_alertingAction(rInt int, rString, location string) string { +func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -149,10 +136,10 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } } -`, rInt, location, rInt, rInt, rInt, ts, ts) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(rInt int, rString, location string) string { +func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -207,10 +194,10 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { threshold = 5000 } } -`, rInt, location, rInt, rInt, rInt, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(rInt int, rString, location string) string { +func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%d" @@ -249,12 +236,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } } -`, rInt, location, rInt, rInt, rInt) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient - ctx := testAccProvider.Meta().(*ArmClient).StopContext + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { if rs.Type != "azurerm_monitor_scheduled_query_rules" { @@ -264,7 +251,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error name := rs.Primary.Attributes["name"] resourceGroup := rs.Primary.Attributes["resource_group_name"] - resp, err := conn.Get(ctx, resourceGroup, name) + resp, err := client.Get(ctx, resourceGroup, name) if err != nil { return nil @@ -292,10 +279,10 @@ func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resou return fmt.Errorf("Bad: no resource group found in state for Activity Log Alert Instance: %s", name) } - conn := testAccProvider.Meta().(*ArmClient).Monitor.ScheduledQueryRulesClient - ctx := testAccProvider.Meta().(*ArmClient).StopContext + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext - resp, err := conn.Get(ctx, resourceGroup, name) + resp, err := client.Get(ctx, resourceGroup, name) if err != nil { return fmt.Errorf("Bad: Get on monitorScheduledQueryRulesClient: %+v", err) } diff --git a/website/docs/d/monitor_scheduled_query_rules.html.markdown b/website/docs/d/monitor_scheduled_query_rules.html.markdown index 804ec3e2606c..d6651611d15b 100644 --- a/website/docs/d/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "" +subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules" From 7b25b377e643117ac99d36e4d128ae7596316614 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Fri, 27 Dec 2019 19:23:26 -0600 Subject: [PATCH 08/25] Add moved tests to registration --- .../internal/services/monitor/registration.go | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/azurerm/internal/services/monitor/registration.go b/azurerm/internal/services/monitor/registration.go index dfc09bd0b42d..366450fc514f 100644 --- a/azurerm/internal/services/monitor/registration.go +++ b/azurerm/internal/services/monitor/registration.go @@ -16,19 +16,21 @@ func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile()} + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules": dataSourceArmMonitorScheduledQueryRules()} } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), - "azurerm_metric_alertrule": resourceArmMetricAlertRule(), - "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), - "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), - "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), - "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), - "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), - "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), - "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule()} + "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), + "azurerm_metric_alertrule": resourceArmMetricAlertRule(), + "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), + "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), + "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), + "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), + "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), + "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), + "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules": resourceArmMonitorScheduledQueryRules()} } From 88a2788596c79f43f0cd77c4919c483b1a266e0b Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 28 Jan 2020 08:54:06 -0600 Subject: [PATCH 09/25] First pass update docs post-review --- ...cheduled_query_rules_action.html.markdown} | 29 ++---- ...or_scheduled_query_rules_log.html.markdown | 54 +++++++++++ ...cheduled_query_rules_action.html.markdown} | 75 ++++------------ ...or_scheduled_query_rules_log.html.markdown | 89 +++++++++++++++++++ 4 files changed, 164 insertions(+), 83 deletions(-) rename website/docs/d/{monitor_scheduled_query_rules.html.markdown => monitor_scheduled_query_rules_action.html.markdown} (77%) create mode 100644 website/docs/d/monitor_scheduled_query_rules_log.html.markdown rename website/docs/r/{monitor_scheduled_query_rules.html.markdown => monitor_scheduled_query_rules_action.html.markdown} (69%) create mode 100644 website/docs/r/monitor_scheduled_query_rules_log.html.markdown diff --git a/website/docs/d/monitor_scheduled_query_rules.html.markdown b/website/docs/d/monitor_scheduled_query_rules_action.html.markdown similarity index 77% rename from website/docs/d/monitor_scheduled_query_rules.html.markdown rename to website/docs/d/monitor_scheduled_query_rules_action.html.markdown index d6651611d15b..e66a2c7ff0c6 100644 --- a/website/docs/d/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_action.html.markdown @@ -1,26 +1,26 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-action" description: |- - Get information about the specified Scheduled Query Rule. + Get information about the specified AlertingAction Scheduled Query Rule. --- # Data Source: azurerm_monitor_scheduled_query_rules -Use this data source to access the properties of a Scheduled Query Rule. +Use this data source to access the properties of an AlertingAction Scheduled Query Rule. ## Example Usage ```hcl -data "azurerm_monitor_scheduled_query_rules" "example" { +data "azurerm_monitor_scheduled_query_rules_action" "example" { resource_group_name = "terraform-example-rg" name = "tfex-queryrule" } output "query_rule_id" { - value = "${data.azurerm_monitor_scheduled_query_rules.example.id}" + value = "${data.azurerm_monitor_scheduled_query_rules_action.example.id}" } ``` @@ -33,9 +33,7 @@ output "query_rule_id" { * `id` - The ID of the Scheduled Query Rule. * `azns_action` - An `azns_action` block as defined below. -* `action_type` - Must equal ether `AlertingAction` or `LogToMetricAction`. * `authorized_resources` - List of Resource IDs referred into query. -* `criteria` - A `criteria` block as defined below. * `data_source_id` - The resource uri over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this scheduled query rule is enabled. @@ -57,21 +55,6 @@ output "query_rule_id" { --- -`criteria` supports the following: - -* `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. - ---- - -`dimension` supports the following: - -* `name` - (Required) Name of the dimension. -* `operator` - (Required) Operator for dimension values, - 'Include'. -* `values` - (Required) List of dimension values. - ---- - `metricTrigger` supports the following: * `metricColumn` - (Required) Evaluation of metric on a particular column. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown new file mode 100644 index 000000000000..a29912472b68 --- /dev/null +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -0,0 +1,54 @@ +--- +subcategory: "Monitor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-log" +description: |- + Get information about the specified LogToMetricAction Scheduled Query Rule. +--- + +# Data Source: azurerm_monitor_scheduled_query_rules_log + +Use this data source to access the properties of a LogToMetricAction Scheduled Query Rule. + +## Example Usage + +```hcl +data "azurerm_monitor_scheduled_query_rules_log" "example" { + resource_group_name = "terraform-example-rg" + name = "tfex-queryrule" +} + +output "query_rule_id" { + value = "${data.azurerm_monitor_scheduled_query_rules_log.example.id}" +} +``` + +## Argument Reference + +* `name` - (Required) Specifies the name of the Scheduled Query Rule. +* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. + +## Attributes Reference + +* `id` - The ID of the Scheduled Query Rule. +* `criteria` - A `criteria` block as defined below. +* `data_source_id` - The resource uri over which log search query is to be run. +* `description` - The description of the Scheduled Query Rule. +* `enabled` - Whether this scheduled query rule is enabled. +* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. diff --git a/website/docs/r/monitor_scheduled_query_rules.html.markdown b/website/docs/r/monitor_scheduled_query_rules_action.html.markdown similarity index 69% rename from website/docs/r/monitor_scheduled_query_rules.html.markdown rename to website/docs/r/monitor_scheduled_query_rules_action.html.markdown index 8d18bebe2327..5bd69d7d22e5 100644 --- a/website/docs/r/monitor_scheduled_query_rules.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_action.html.markdown @@ -1,15 +1,15 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-action" description: |- - Manages a Scheduled Query Rule within Azure Monitor + Manages an AlertingAction Scheduled Query Rule within Azure Monitor --- -# azurerm_monitor_action_group +# azurerm_monitor_scheduled_query_rules_action -Manages a Scheduled Query Rule within Azure Monitor. +Manages an AlertingAction Scheduled Query Rule within Azure Monitor. ## Example Usage @@ -35,12 +35,11 @@ resource "azurerm_log_analytics_workspace" "example" { } # Example: Alerting Action -resource "azurerm_scheduled_query_rule" "example" { +resource "azurerm_scheduled_query_rule_action" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "Alerting" azns_action { action_group = [] email_subject = "Email Header" @@ -67,12 +66,11 @@ resource "azurerm_scheduled_query_rule" "example" { } # Example: Alerting Action Cross-Resource -resource "azurerm_scheduled_query_rule" "example2" { +resource "azurerm_scheduled_query_rule_action" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - action_type = "Alerting" authorized_resources = [azurerm_application_insights.example.id, azurerm_log_analytics_workspace.example.id] azns_action { @@ -93,26 +91,6 @@ resource "azurerm_scheduled_query_rule" "example2" { threshold = 3 } } - -# Example: LogToMetric Action -resource "azurerm_scheduled_query_rule" "example3" { - name = format("%s-queryrule3", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - - action_type = "LogToMetric" - criteria { - metric_name = "Average_% Idle Time" - dimensions { - name = "InstanceName" - operator = "Include" - values = [""] - } - } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule LogToMetric example" - enabled = true -} ``` ## Argument Reference @@ -121,26 +99,18 @@ The following arguments are supported: * `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. -* `action_type` - (Required) Must equal ether `AlertingAction` or `LogToMetricAction`. * `authorized_resources` - (Optional) List of Resource IDs referred into query. +* `azns_action` - (Optional) An `azns_action` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. - -The following arguments are only supported when `action_type` is `AlertingAction`: - -* `azns_action` - (Optional) An `azns_action` block as defined below. -* `frequency` - (Optional) Frequency (in minutes) at which rule condition should be evaluated. Required when `action_type` is `AlertingAction`. -* `query` - (Optional) Log search query. Required when `action_type` is `AlertingAction`. -* `query_type` - (Optional) Must equal "ResultCount" for now. Required when `action_type` is `AlertingAction`. +* `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. +* `query` - (Required) Log search query. +* `query_type` - (Required) Must equal "ResultCount" for now. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. -* `time_window` - (Optional) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). Required when `action_type` is `AlertingAction`. -* `trigger` - (Optional) The condition that results in the alert rule being run. Required when `action_type` is `AlertingAction`. - -The following arguments are only supported when `action_type` is `LogToMetricAction`: - -* `criteria` - (Optional) A `criteria` block as defined below. Required when `action_type` is `LogToMetricAction`. +* `time_window` - (Required) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. +* `trigger` - (Required) The condition that results in the alert rule being run. --- @@ -152,21 +122,6 @@ The following arguments are only supported when `action_type` is `LogToMetricAct --- -`criteria` supports the following: - -* `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. - ---- - -`dimension` supports the following: - -* `name` - (Required) Name of the dimension. -* `operator` - (Required) Operator for dimension values, - 'Include'. -* `values` - (Required) List of dimension values. - ---- - `metricTrigger` supports the following: * `metricColumn` - (Required) Evaluation of metric on a particular column. @@ -195,5 +150,5 @@ The following attributes are exported: Scheduled Query Rules can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_monitor_scheduled_query_rules.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +terraform import azurerm_monitor_scheduled_query_rules_action.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename ``` diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown new file mode 100644 index 000000000000..a5d6895fb301 --- /dev/null +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -0,0 +1,89 @@ +--- +subcategory: "Monitor" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-log" +description: |- + Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor +--- + +# azurerm_monitor_scheduled_query_rules_log + +Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "monitoring-resources" + location = "West US" +} + +resource "azurerm_application_insights" "example" { + name = "appinsights" + location = var.location + resource_group_name = azurerm_resource_group.example.name + application_type = "web" +} + +resource "azurerm_scheduled_query_rule_log" "example3" { + name = format("%s-queryrule3", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + criteria { + metric_name = "Average_% Idle Time" + dimensions { + name = "InstanceName" + operator = "Include" + values = [""] + } + } + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule LogToMetric example" + enabled = true +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `criteria` - (Required) A `criteria` block as defined below. +* `data_source_id` - (Required) The resource uri over which log search query is to be run. +* `description` - (Optional) The description of the Scheduled Query Rule. +* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. + +--- + +`criteria` supports the following: + +* `dimension` - (Required) A `dimension` block as defined below. +* `metric_name` - (Required) Name of the metric. + +--- + +`dimension` supports the following: + +* `name` - (Required) Name of the dimension. +* `operator` - (Required) Operator for dimension values, - 'Include'. +* `values` - (Required) List of dimension values. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Scheduled Query Rule. +* `last_updated_time` - Last time the rule was updated in IS08601 format. +* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' + +## Import + +Scheduled Query Rules can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_monitor_scheduled_query_rules_log.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +``` From 3dcea9c3a267bc4492042266973d10e99b7b1907 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 28 Jan 2020 09:25:34 -0600 Subject: [PATCH 10/25] First pass at separating into two resources --- ...e_monitor_scheduled_query_rules_action.go} | 44 +- ...ource_monitor_scheduled_query_rules_log.go | 252 +++++++++ .../internal/services/monitor/registration.go | 30 +- ...m_monitor_scheduled_query_rules_action.go} | 185 +------ ...e_arm_monitor_scheduled_query_rules_log.go | 477 ++++++++++++++++++ ...itor_scheduled_query_rules_action_test.go} | 0 ..._monitor_scheduled_query_rules_log_test.go | 243 +++++++++ ...itor_scheduled_query_rules_action_test.go} | 75 +-- ..._monitor_scheduled_query_rules_log_test.go | 133 +++++ 9 files changed, 1164 insertions(+), 275 deletions(-) rename azurerm/internal/services/monitor/{data_source_monitor_scheduled_query_rules.go => data_source_monitor_scheduled_query_rules_action.go} (80%) create mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go rename azurerm/internal/services/monitor/{resource_arm_monitor_scheduled_query_rules.go => resource_arm_monitor_scheduled_query_rules_action.go} (71%) create mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go rename azurerm/internal/services/monitor/tests/{data_source_monitor_scheduled_query_rules_test.go => data_source_monitor_scheduled_query_rules_action_test.go} (100%) create mode 100644 azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go rename azurerm/internal/services/monitor/tests/{resource_arm_monitor_scheduled_query_rules_test.go => resource_arm_monitor_scheduled_query_rules_action_test.go} (77%) create mode 100644 azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go similarity index 80% rename from azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go rename to azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go index 49e77b42c439..675173520cc9 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go @@ -14,9 +14,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { +func dataSourceArmMonitorScheduledQueryRulesAction() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesRead, + Read: dataSourceArmMonitorScheduledQueryRulesActionRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -32,10 +32,6 @@ func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { "location": azure.SchemaLocationForDataSource(), - "action_type": { - Type: schema.TypeString, - Computed: true, - }, "authorized_resources": { Type: schema.TypeSet, Computed: true, @@ -192,7 +188,7 @@ func dataSourceArmMonitorScheduledQueryRules() *schema.Resource { } } -func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -221,28 +217,18 @@ func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta in d.Set("enabled", false) } - switch action := resp.Action.(type) { - case insights.AlertingAction: - d.Set("action_type", "Alerting") - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `azns_action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - case insights.LogToMetricAction: - d.Set("action_type", "LogToMetric") - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + var action insights.AlertingAction + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `azns_action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) } if schedule := resp.Schedule; schedule != nil { diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go new file mode 100644 index 000000000000..ff14ae0516ea --- /dev/null +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -0,0 +1,252 @@ +package monitor + +import ( + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmMonitorScheduledQueryRulesLogRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "authorized_resources": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Computed: true, + }, + "email_subject": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Elem: schema.TypeString, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "values": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Computed: true, + }, + "query_type": { + Type: schema.TypeString, + Computed: true, + }, + "severity": { + Type: schema.TypeInt, + Computed: true, + }, + "throttling": { + Type: schema.TypeInt, + Computed: true, + }, + "time_window": { + Type: schema.TypeInt, + Computed: true, + }, + "trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Computed: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Computed: true, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} + +func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + var action insights.LogToMetricAction + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/registration.go b/azurerm/internal/services/monitor/registration.go index 366450fc514f..d4aeb8e97123 100644 --- a/azurerm/internal/services/monitor/registration.go +++ b/azurerm/internal/services/monitor/registration.go @@ -14,23 +14,25 @@ func (r Registration) Name() string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_monitor_scheduled_query_rules": dataSourceArmMonitorScheduledQueryRules()} + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules_action": dataSourceArmMonitorScheduledQueryRulesAction(), + "azurerm_monitor_scheduled_query_rules_log": dataSourceArmMonitorScheduledQueryRulesLog()} } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), - "azurerm_metric_alertrule": resourceArmMetricAlertRule(), - "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), - "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), - "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), - "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), - "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), - "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), - "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), - "azurerm_monitor_scheduled_query_rules": resourceArmMonitorScheduledQueryRules()} + "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), + "azurerm_metric_alertrule": resourceArmMetricAlertRule(), + "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), + "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), + "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), + "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), + "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), + "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), + "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules_action": resourceArmMonitorScheduledQueryRulesAction(), + "azurerm_monitor_scheduled_query_rules_log": resourceArmMonitorScheduledQueryRulesLog()} } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go similarity index 71% rename from azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go rename to azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go index 7a924f78ac16..ff774f53231f 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go @@ -20,12 +20,12 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func resourceArmMonitorScheduledQueryRules() *schema.Resource { +func resourceArmMonitorScheduledQueryRulesAction() *schema.Resource { return &schema.Resource{ - Create: resourceArmMonitorScheduledQueryRulesCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesRead, - Update: resourceArmMonitorScheduledQueryRulesCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesDelete, + Create: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesActionRead, + Update: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesActionDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -49,14 +49,6 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { "location": azure.SchemaLocation(), - "action_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Alerting", - "LogToMetric", - }, false), - }, "authorized_resources": { Type: schema.TypeSet, Optional: true, @@ -89,44 +81,6 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { }, }, }, - "criteria": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dimension": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Include", - }, false), - }, - "values": { - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "metric_name": { - Type: schema.TypeString, - Required: true, - }, - }, - }, - }, "data_source_id": { Type: schema.TypeString, Required: true, @@ -245,7 +199,7 @@ func resourceArmMonitorScheduledQueryRules() *schema.Resource { } } -func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceArmMonitorScheduledQueryRulesActionCreateUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -262,11 +216,10 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m } if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules", *existing.ID) + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_action", *existing.ID) } } - actionType := d.Get("action_type").(string) description := d.Get("description").(string) enabledRaw := d.Get("enabled").(bool) @@ -278,15 +231,7 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m location := azure.NormalizeLocation(d.Get("location")) var action insights.BasicAction - switch actionType { - case "Alerting": - action = expandMonitorScheduledQueryRulesAlertingAction(d) - case "LogToMetric": - action = expandMonitorScheduledQueryRulesLogToMetricAction(d) - default: - return fmt.Errorf("Invalid action_type %q. Value must be either 'Alerting' or 'LogToMetric'", actionType) - } - + action = expandMonitorScheduledQueryRulesAlertingAction(d) source := expandMonitorScheduledQueryRulesSource(d) schedule := expandMonitorScheduledQueryRulesSchedule(d) @@ -318,10 +263,10 @@ func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, m } d.SetId(*read.ID) - return resourceArmMonitorScheduledQueryRulesRead(d, meta) + return resourceArmMonitorScheduledQueryRulesActionRead(d, meta) } -func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { +func resourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -363,8 +308,7 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte switch action := resp.Action.(type) { case insights.AlertingAction: - d.Set("action_type", "Alerting") - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesAznsAction(action.AznsAction)); err != nil { + if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `azns_action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -373,14 +317,9 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } - case insights.LogToMetricAction: - d.Set("action_type", "LogToMetric") - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } default: return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } @@ -410,7 +349,7 @@ func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta inte return tags.FlattenAndSet(d, resp.Tags) } -func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { +func resourceArmMonitorScheduledQueryRulesActionDelete(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() @@ -433,13 +372,13 @@ func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta in func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { aznsActionRaw := d.Get("azns_action").(*schema.Set).List() - aznsAction := expandMonitorScheduledQueryRulesAznsAction(aznsActionRaw) + aznsAction := expandMonitorScheduledQueryRulesActionAznsAction(aznsActionRaw) severityRaw := d.Get("severity").(int) severity := strconv.Itoa(severityRaw) throttling := d.Get("throttling").(int) triggerRaw := d.Get("trigger").(*schema.Set).List() - trigger := expandMonitorScheduledQueryRulesTrigger(triggerRaw) + trigger := expandMonitorScheduledQueryRulesActionTrigger(triggerRaw) action := insights.AlertingAction{ AznsAction: aznsAction, @@ -452,7 +391,7 @@ func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *ins return &action } -func expandMonitorScheduledQueryRulesAznsAction(input []interface{}) *insights.AzNsActionGroup { +func expandMonitorScheduledQueryRulesActionAznsAction(input []interface{}) *insights.AzNsActionGroup { result := insights.AzNsActionGroup{} for _, item := range input { @@ -467,41 +406,6 @@ func expandMonitorScheduledQueryRulesAznsAction(input []interface{}) *insights.A return &result } -func expandMonitorScheduledQueryRulesCriteria(input []interface{}) *[]insights.Criteria { - criteria := make([]insights.Criteria, 0) - for _, item := range input { - v := item.(map[string]interface{}) - - dimensions := make([]insights.Dimension, 0) - for _, dimension := range v["dimension"].(*schema.Set).List() { - dVal := dimension.(map[string]interface{}) - dimensions = append(dimensions, insights.Dimension{ - Name: utils.String(dVal["name"].(string)), - Operator: utils.String(dVal["operator"].(string)), - Values: utils.ExpandStringSlice(dVal["values"].([]interface{})), - }) - } - - criteria = append(criteria, insights.Criteria{ - MetricName: utils.String(v["metric_name"].(string)), - Dimensions: &dimensions, - }) - } - return &criteria -} - -func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { - criteriaRaw := d.Get("criteria").(*schema.Set).List() - criteria := expandMonitorScheduledQueryRulesCriteria(criteriaRaw) - - action := insights.LogToMetricAction{ - Criteria: criteria, - OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesLogToMetricAction, - } - - return &action -} - func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights.Schedule { frequency := d.Get("frequency").(int) timeWindow := d.Get("time_window").(int) @@ -514,7 +418,7 @@ func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights. return &schedule } -func expandMonitorScheduledQueryRulesMetricTrigger(input []interface{}) *insights.LogMetricTrigger { +func expandMonitorScheduledQueryRulesActionMetricTrigger(input []interface{}) *insights.LogMetricTrigger { if len(input) == 0 { return nil } @@ -546,7 +450,7 @@ func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.So return &source } -func expandMonitorScheduledQueryRulesTrigger(input []interface{}) *insights.TriggerCondition { +func expandMonitorScheduledQueryRulesActionTrigger(input []interface{}) *insights.TriggerCondition { result := insights.TriggerCondition{} for _, item := range input { @@ -555,13 +459,13 @@ func expandMonitorScheduledQueryRulesTrigger(input []interface{}) *insights.Trig result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) result.Threshold = utils.Float(v["threshold"].(float64)) - result.MetricTrigger = expandMonitorScheduledQueryRulesMetricTrigger(metricTriggerRaw) + result.MetricTrigger = expandMonitorScheduledQueryRulesActionMetricTrigger(metricTriggerRaw) } return &result } -func flattenAzureRmScheduledQueryRulesAznsAction(input *insights.AzNsActionGroup) []interface{} { +func flattenAzureRmScheduledQueryRulesActionAznsAction(input *insights.AzNsActionGroup) []interface{} { result := make([]interface{}, 0) v := make(map[string]interface{}) @@ -577,50 +481,7 @@ func flattenAzureRmScheduledQueryRulesAznsAction(input *insights.AzNsActionGroup return result } -func flattenAzureRmScheduledQueryRulesCriteria(input *[]insights.Criteria) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, criteria := range *input { - v := make(map[string]interface{}) - - v["dimension"] = flattenAzureRmScheduledQueryRulesDimension(criteria.Dimensions) - v["metric_name"] = *criteria.MetricName - - result = append(result, v) - } - } - - return result -} - -func flattenAzureRmScheduledQueryRulesDimension(input *[]insights.Dimension) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, dimension := range *input { - v := make(map[string]interface{}) - - if dimension.Name != nil { - v["name"] = *dimension.Name - } - - if dimension.Operator != nil { - v["operator"] = *dimension.Operator - } - - if dimension.Values != nil { - v["values"] = *dimension.Values - } - - result = append(result, v) - } - } - - return result -} - -func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTrigger) []interface{} { +func flattenAzureRmScheduledQueryRulesActionMetricTrigger(input *insights.LogMetricTrigger) []interface{} { result := make(map[string]interface{}) if input == nil { @@ -641,7 +502,7 @@ func flattenAzureRmScheduledQueryRulesMetricTrigger(input *insights.LogMetricTri return []interface{}{result} } -func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) []interface{} { +func flattenAzureRmScheduledQueryRulesActionTrigger(input *insights.TriggerCondition) []interface{} { result := make(map[string]interface{}) result["operator"] = string(input.ThresholdOperator) @@ -651,7 +512,7 @@ func flattenAzureRmScheduledQueryRulesTrigger(input *insights.TriggerCondition) } if input.MetricTrigger != nil { - result["metric_trigger"] = flattenAzureRmScheduledQueryRulesMetricTrigger(input.MetricTrigger) + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesActionMetricTrigger(input.MetricTrigger) } return []interface{}{result} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go new file mode 100644 index 000000000000..1167d81da80e --- /dev/null +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -0,0 +1,477 @@ +package monitor + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesLogRead, + Update: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesLogDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "authorized_resources": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "azns_action": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Optional: true, + Default: "{}", + ValidateFunc: validation.ValidateJsonString, + }, + "email_subject": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "criteria": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimension": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Include", + }, false), + }, + "values": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "metric_name": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "frequency": { + Type: schema.TypeInt, + Optional: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + }, + "query_type": { + Type: schema.TypeString, + Optional: true, + Default: "ResultCount", + ValidateFunc: validation.StringInSlice([]string{ + "ResultCount", + }, false), + }, + "severity": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{ + 0, + 1, + 2, + 3, + 4, + }), + }, + "throttling": { + Type: schema.TypeInt, + Optional: true, + }, + "time_window": { + Type: schema.TypeInt, + Optional: true, + }, + "trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Required: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Consecutive", + "Total", + }, false), + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_log", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + var action insights.BasicAction + action = expandMonitorScheduledQueryRulesLogToMetricAction(d) + source := expandMonitorScheduledQueryRulesSource(d) + schedule := expandMonitorScheduledQueryRulesSchedule(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesLogRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + switch action := resp.Action.(type) { + case insights.LogToMetricAction: + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insights.Criteria { + criteria := make([]insights.Criteria, 0) + for _, item := range input { + v := item.(map[string]interface{}) + + dimensions := make([]insights.Dimension, 0) + for _, dimension := range v["dimension"].(*schema.Set).List() { + dVal := dimension.(map[string]interface{}) + dimensions = append(dimensions, insights.Dimension{ + Name: utils.String(dVal["name"].(string)), + Operator: utils.String(dVal["operator"].(string)), + Values: utils.ExpandStringSlice(dVal["values"].([]interface{})), + }) + } + + criteria = append(criteria, insights.Criteria{ + MetricName: utils.String(v["metric_name"].(string)), + Dimensions: &dimensions, + }) + } + return &criteria +} + +func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { + criteriaRaw := d.Get("criteria").(*schema.Set).List() + criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) + + action := insights.LogToMetricAction{ + Criteria: criteria, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesLogToMetricAction, + } + + return &action +} + +func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, criteria := range *input { + v := make(map[string]interface{}) + + v["dimension"] = flattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) + v["metric_name"] = *criteria.MetricName + + result = append(result, v) + } + } + + return result +} + +func flattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, dimension := range *input { + v := make(map[string]interface{}) + + if dimension.Name != nil { + v["name"] = *dimension.Name + } + + if dimension.Operator != nil { + v["operator"] = *dimension.Operator + } + + if dimension.Values != nil { + v["values"] = *dimension.Values + } + + result = append(result, v) + } + } + + return result +} diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go similarity index 100% rename from azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go new file mode 100644 index 000000000000..875fdaa76202 --- /dev/null +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -0,0 +1,243 @@ +package tests + +import ( + "fmt" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" +) + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), + ), + }, + }, + }) +} + +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(data.ResourceName, "id"), + ), + }, + }, + }) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = [""] + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} + +func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { + ts := time.Now().Format(time.RFC3339) + + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_log_analytics_workspace" "test2" { + name = "acctestWorkspace2-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules" "test" { + name = "acctestSqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test alerting action" + enabled = true + action_type = "Alerting" + + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + + frequency = 60 + time_window = 60 + + severity = 3 + azns_action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } +} + +data "azurerm_monitor_scheduled_query_rules" "test" { + name = "${azurerm_monitor_scheduled_query_rules.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go similarity index 77% rename from azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go rename to azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go index 357a8ba2b0f9..1bb822ff80a2 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go @@ -13,7 +13,7 @@ import ( ) func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -36,7 +36,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -58,29 +58,6 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }) } -func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), - Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), - ), - }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) @@ -103,7 +80,7 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_action" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" @@ -167,7 +144,7 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_action" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" @@ -197,54 +174,12 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - action_type = "LogToMetric" - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = [""] - } - } -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_monitor_scheduled_query_rules" { + if rs.Type != "azurerm_monitor_scheduled_query_rules_action" { continue } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go new file mode 100644 index 000000000000..069f41ae89e7 --- /dev/null +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -0,0 +1,133 @@ +package tests + +import ( + "fmt" + "net/http" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" +) + +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + ), + }, + { + ResourceName: data.ResourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + action_type = "LogToMetric" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = [""] + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_monitor_scheduled_query_rules_log" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := client.Get(ctx, resourceGroup, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + } + } + + return nil +} + +func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Activity Log Alert Instance: %s", name) + } + + client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("Bad: Get on monitorScheduledQueryRulesClient: %+v", err) + } + + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + } + + return nil + } +} From 27f7f4fa0ccd45f6d6a6a19bd133f02c2b2c86d3 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Wed, 29 Jan 2020 08:45:43 -0600 Subject: [PATCH 11/25] Rename action to alert in docs --- ...onitor_scheduled_query_rules_alert.html.markdown} | 10 +++++----- ...onitor_scheduled_query_rules_alert.html.markdown} | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) rename website/docs/d/{monitor_scheduled_query_rules_action.html.markdown => monitor_scheduled_query_rules_alert.html.markdown} (92%) rename website/docs/r/{monitor_scheduled_query_rules_action.html.markdown => monitor_scheduled_query_rules_alert.html.markdown} (93%) diff --git a/website/docs/d/monitor_scheduled_query_rules_action.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown similarity index 92% rename from website/docs/d/monitor_scheduled_query_rules_action.html.markdown rename to website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index e66a2c7ff0c6..4d92728a8984 100644 --- a/website/docs/d/monitor_scheduled_query_rules_action.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -1,26 +1,26 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-action" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" +sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-alert" description: |- Get information about the specified AlertingAction Scheduled Query Rule. --- -# Data Source: azurerm_monitor_scheduled_query_rules +# Data Source: azurerm_monitor_scheduled_query_rules_alert Use this data source to access the properties of an AlertingAction Scheduled Query Rule. ## Example Usage ```hcl -data "azurerm_monitor_scheduled_query_rules_action" "example" { +data "azurerm_monitor_scheduled_query_rules_alert" "example" { resource_group_name = "terraform-example-rg" name = "tfex-queryrule" } output "query_rule_id" { - value = "${data.azurerm_monitor_scheduled_query_rules_action.example.id}" + value = "${data.azurerm_monitor_scheduled_query_rules_alert.example.id}" } ``` diff --git a/website/docs/r/monitor_scheduled_query_rules_action.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown similarity index 93% rename from website/docs/r/monitor_scheduled_query_rules_action.html.markdown rename to website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 5bd69d7d22e5..d78cbf5c4eec 100644 --- a/website/docs/r/monitor_scheduled_query_rules_action.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -1,13 +1,13 @@ --- subcategory: "Monitor" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_action" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-action" +page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" +sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-alert" description: |- Manages an AlertingAction Scheduled Query Rule within Azure Monitor --- -# azurerm_monitor_scheduled_query_rules_action +# azurerm_monitor_scheduled_query_rules_alert Manages an AlertingAction Scheduled Query Rule within Azure Monitor. @@ -35,7 +35,7 @@ resource "azurerm_log_analytics_workspace" "example" { } # Example: Alerting Action -resource "azurerm_scheduled_query_rule_action" "example" { +resource "azurerm_scheduled_query_rule_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name @@ -66,7 +66,7 @@ resource "azurerm_scheduled_query_rule_action" "example" { } # Example: Alerting Action Cross-Resource -resource "azurerm_scheduled_query_rule_action" "example2" { +resource "azurerm_scheduled_query_rule_alert" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name @@ -150,5 +150,5 @@ The following attributes are exported: Scheduled Query Rules can be imported using the `resource id`, e.g. ```shell -terraform import azurerm_monitor_scheduled_query_rules_action.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename +terraform import azurerm_monitor_scheduled_query_rules_alert.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/scheduledQueryRules/myrulename ``` From 7dfdeb34ae35c43c571db2a16c8f7f39d7fb75eb Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 11:31:08 -0600 Subject: [PATCH 12/25] Fix code review items --- ...ta_source_monitor_scheduled_query_rules.go | 96 ++++ ...ce_monitor_scheduled_query_rules_action.go | 262 --------- ...rce_monitor_scheduled_query_rules_alert.go | 147 +++++ ...ource_monitor_scheduled_query_rules_log.go | 152 +---- .../internal/services/monitor/registration.go | 32 +- ...ource_arm_monitor_scheduled_query_rules.go | 207 +++++++ ...rm_monitor_scheduled_query_rules_action.go | 519 ------------------ ...arm_monitor_scheduled_query_rules_alert.go | 336 ++++++++++++ ...e_arm_monitor_scheduled_query_rules_log.go | 323 ++--------- ...nitor_scheduled_query_rules_alert_test.go} | 92 +--- ..._monitor_scheduled_query_rules_log_test.go | 185 +------ ...nitor_scheduled_query_rules_alert_test.go} | 28 +- ..._monitor_scheduled_query_rules_log_test.go | 7 +- ..._scheduled_query_rules_alert.html.markdown | 22 +- ...or_scheduled_query_rules_log.html.markdown | 10 +- ..._scheduled_query_rules_alert.html.markdown | 14 +- 16 files changed, 895 insertions(+), 1537 deletions(-) create mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go delete mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go create mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go create mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go delete mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go create mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go rename azurerm/internal/services/monitor/tests/{data_source_monitor_scheduled_query_rules_action_test.go => data_source_monitor_scheduled_query_rules_alert_test.go} (65%) rename azurerm/internal/services/monitor/tests/{resource_arm_monitor_scheduled_query_rules_action_test.go => resource_arm_monitor_scheduled_query_rules_alert_test.go} (84%) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go new file mode 100644 index 000000000000..72380eedcbd3 --- /dev/null +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go @@ -0,0 +1,96 @@ +package monitor + +import ( + "fmt" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + switch action := resp.Action.(type) { + case insights.AlertingAction: + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + case insights.LogToMetricAction: + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go deleted file mode 100644 index 675173520cc9..000000000000 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_action.go +++ /dev/null @@ -1,262 +0,0 @@ -package monitor - -import ( - "fmt" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func dataSourceArmMonitorScheduledQueryRulesAction() *schema.Resource { - return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesActionRead, - - Timeouts: &schema.ResourceTimeout{ - Read: schema.DefaultTimeout(5 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - }, - - "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), - - "location": azure.SchemaLocationForDataSource(), - - "authorized_resources": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "azns_action": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Computed: true, - }, - "email_subject": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "criteria": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dimension": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Computed: true, - Elem: schema.TypeString, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "values": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, - }, - "metric_name": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - "data_source_id": { - Type: schema.TypeString, - Computed: true, - }, - "description": { - Type: schema.TypeString, - Computed: true, - }, - "enabled": { - Type: schema.TypeBool, - Computed: true, - }, - "frequency": { - Type: schema.TypeInt, - Computed: true, - }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, - "query": { - Type: schema.TypeString, - Computed: true, - }, - "query_type": { - Type: schema.TypeString, - Computed: true, - }, - "severity": { - Type: schema.TypeInt, - Computed: true, - }, - "throttling": { - Type: schema.TypeInt, - Computed: true, - }, - "time_window": { - Type: schema.TypeInt, - Computed: true, - }, - "trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Computed: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Computed: true, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, - - "tags": tags.SchemaDataSource(), - }, - } -} - -func dataSourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) - } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) - } - - d.SetId(*resp.ID) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - d.Set("description", resp.Description) - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - var action insights.AlertingAction - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `azns_action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - return tags.FlattenAndSet(d, resp.Tags) -} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go new file mode 100644 index 000000000000..c7dc42763af8 --- /dev/null +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -0,0 +1,147 @@ +package monitor + +import ( + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" +) + +func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { + return &schema.Resource{ + Read: dataSourceArmMonitorScheduledQueryRulesRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(5 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "resource_group_name": azure.SchemaResourceGroupNameForDataSource(), + + "location": azure.SchemaLocationForDataSource(), + + "authorized_resource_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "action": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Computed: true, + }, + "email_subject": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "frequency": { + Type: schema.TypeInt, + Computed: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Computed: true, + }, + "query_type": { + Type: schema.TypeString, + Computed: true, + }, + "severity": { + Type: schema.TypeInt, + Computed: true, + }, + "throttling": { + Type: schema.TypeInt, + Computed: true, + }, + "time_window": { + Type: schema.TypeInt, + Computed: true, + }, + "trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Computed: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Computed: true, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Computed: true, + }, + "threshold": { + Type: schema.TypeFloat, + Computed: true, + }, + }, + }, + }, + + "tags": tags.SchemaDataSource(), + }, + } +} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index ff14ae0516ea..cd0853c6dc72 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -1,21 +1,16 @@ package monitor import ( - "fmt" "time" - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesLogRead, + Read: dataSourceArmMonitorScheduledQueryRulesRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -31,36 +26,13 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "location": azure.SchemaLocationForDataSource(), - "authorized_resources": { + "authorized_resource_ids": { Type: schema.TypeSet, Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, }, - "azns_action": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Computed: true, - }, - "email_subject": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, "criteria": { Type: schema.TypeSet, Computed: true, @@ -109,10 +81,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "frequency": { - Type: schema.TypeInt, - Computed: true, - }, "last_updated_time": { Type: schema.TypeString, Computed: true, @@ -129,124 +97,8 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "severity": { - Type: schema.TypeInt, - Computed: true, - }, - "throttling": { - Type: schema.TypeInt, - Computed: true, - }, - "time_window": { - Type: schema.TypeInt, - Computed: true, - }, - "trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Computed: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Computed: true, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Computed: true, - }, - "threshold": { - Type: schema.TypeFloat, - Computed: true, - }, - }, - }, - }, "tags": tags.SchemaDataSource(), }, } } - -func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) - } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) - } - - d.SetId(*resp.ID) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - d.Set("description", resp.Description) - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - var action insights.LogToMetricAction - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - return tags.FlattenAndSet(d, resp.Tags) -} diff --git a/azurerm/internal/services/monitor/registration.go b/azurerm/internal/services/monitor/registration.go index d4aeb8e97123..495c3fbb4d4a 100644 --- a/azurerm/internal/services/monitor/registration.go +++ b/azurerm/internal/services/monitor/registration.go @@ -14,25 +14,25 @@ func (r Registration) Name() string { // SupportedDataSources returns the supported Data Sources supported by this Service func (r Registration) SupportedDataSources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), - "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), - "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), - "azurerm_monitor_scheduled_query_rules_action": dataSourceArmMonitorScheduledQueryRulesAction(), - "azurerm_monitor_scheduled_query_rules_log": dataSourceArmMonitorScheduledQueryRulesLog()} + "azurerm_monitor_action_group": dataSourceArmMonitorActionGroup(), + "azurerm_monitor_diagnostic_categories": dataSourceArmMonitorDiagnosticCategories(), + "azurerm_monitor_log_profile": dataSourceArmMonitorLogProfile(), + "azurerm_monitor_scheduled_query_rules_alert": dataSourceArmMonitorScheduledQueryRulesAlert(), + "azurerm_monitor_scheduled_query_rules_log": dataSourceArmMonitorScheduledQueryRulesLog()} } // SupportedResources returns the supported Resources supported by this Service func (r Registration) SupportedResources() map[string]*schema.Resource { return map[string]*schema.Resource{ - "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), - "azurerm_metric_alertrule": resourceArmMetricAlertRule(), - "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), - "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), - "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), - "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), - "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), - "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), - "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), - "azurerm_monitor_scheduled_query_rules_action": resourceArmMonitorScheduledQueryRulesAction(), - "azurerm_monitor_scheduled_query_rules_log": resourceArmMonitorScheduledQueryRulesLog()} + "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), + "azurerm_metric_alertrule": resourceArmMetricAlertRule(), + "azurerm_monitor_autoscale_setting": resourceArmMonitorAutoScaleSetting(), + "azurerm_monitor_action_group": resourceArmMonitorActionGroup(), + "azurerm_monitor_activity_log_alert": resourceArmMonitorActivityLogAlert(), + "azurerm_monitor_diagnostic_setting": resourceArmMonitorDiagnosticSetting(), + "azurerm_monitor_log_profile": resourceArmMonitorLogProfile(), + "azurerm_monitor_metric_alert": resourceArmMonitorMetricAlert(), + "azurerm_monitor_metric_alertrule": resourceArmMonitorMetricAlertRule(), + "azurerm_monitor_scheduled_query_rules_alert": resourceArmMonitorScheduledQueryRulesAlert(), + "azurerm_monitor_scheduled_query_rules_log": resourceArmMonitorScheduledQueryRulesLog()} } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go new file mode 100644 index 000000000000..b7661870314a --- /dev/null +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go @@ -0,0 +1,207 @@ +package monitor + +import ( + "fmt" + "log" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}, action insights.BasicAction, schedule *insights.Schedule) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + source := expandMonitorScheduledQueryRulesSource(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { + d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) + } + d.Set("provisioning_state", resp.ProvisioningState) + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + switch action := resp.Action.(type) { + case insights.AlertingAction: + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + case insights.LogToMetricAction: + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + default: + return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query, ok := d.Get("query").(string) + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + if ok { + source.Query = utils.String(query) + } + + return &source +} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go deleted file mode 100644 index ff774f53231f..000000000000 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_action.go +++ /dev/null @@ -1,519 +0,0 @@ -package monitor - -import ( - "fmt" - "log" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/go-azure-helpers/response" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmMonitorScheduledQueryRulesAction() *schema.Resource { - return &schema.Resource{ - Create: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesActionRead, - Update: resourceArmMonitorScheduledQueryRulesActionCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesActionDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, - }, - - "resource_group_name": azure.SchemaResourceGroupName(), - - "location": azure.SchemaLocation(), - - "authorized_resources": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "azns_action": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Optional: true, - Default: "{}", - ValidateFunc: validation.ValidateJsonString, - }, - "email_subject": { - Type: schema.TypeString, - Optional: true, - }, - }, - }, - }, - "data_source_id": { - Type: schema.TypeString, - Required: true, - ValidateFunc: azure.ValidateResourceID, - }, - "description": { - Type: schema.TypeString, - Optional: true, - }, - "enabled": { - Type: schema.TypeBool, - Optional: true, - Default: true, - }, - "frequency": { - Type: schema.TypeInt, - Optional: true, - }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, - "query": { - Type: schema.TypeString, - Optional: true, - }, - "query_type": { - Type: schema.TypeString, - Optional: true, - Default: "ResultCount", - ValidateFunc: validation.StringInSlice([]string{ - "ResultCount", - }, false), - }, - "severity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntInSlice([]int{ - 0, - 1, - 2, - 3, - 4, - }), - }, - "throttling": { - Type: schema.TypeInt, - Optional: true, - }, - "time_window": { - Type: schema.TypeInt, - Optional: true, - }, - "trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Required: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Consecutive", - "Total", - }, false), - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - ValidateFunc: validation.NoZeroValues, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - }, - }, - }, - }, - - "tags": tags.Schema(), - }, - } -} - -func resourceArmMonitorScheduledQueryRulesActionCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_action", *existing.ID) - } - } - - description := d.Get("description").(string) - enabledRaw := d.Get("enabled").(bool) - - enabled := insights.True - if !enabledRaw { - enabled = insights.False - } - - location := azure.NormalizeLocation(d.Get("location")) - - var action insights.BasicAction - action = expandMonitorScheduledQueryRulesAlertingAction(d) - source := expandMonitorScheduledQueryRulesSource(d) - schedule := expandMonitorScheduledQueryRulesSchedule(d) - - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - - parameters := insights.LogSearchRuleResource{ - Location: utils.String(location), - LogSearchRule: &insights.LogSearchRule{ - Description: utils.String(description), - Enabled: enabled, - Source: source, - Schedule: schedule, - Action: action, - }, - Tags: expandedTags, - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - read, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return err - } - if read.ID == nil { - return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) - } - d.SetId(*read.ID) - - return resourceArmMonitorScheduledQueryRulesActionRead(d, meta) -} - -func resourceArmMonitorScheduledQueryRulesActionRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) - d.SetId("") - return nil - } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - d.Set("description", resp.Description) - - switch action := resp.Action.(type) { - case insights.AlertingAction: - if err = d.Set("azns_action", flattenAzureRmScheduledQueryRulesActionAznsAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `azns_action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesActionTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmMonitorScheduledQueryRulesActionDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { - if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - } - - return nil -} - -func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { - aznsActionRaw := d.Get("azns_action").(*schema.Set).List() - aznsAction := expandMonitorScheduledQueryRulesActionAznsAction(aznsActionRaw) - severityRaw := d.Get("severity").(int) - severity := strconv.Itoa(severityRaw) - throttling := d.Get("throttling").(int) - - triggerRaw := d.Get("trigger").(*schema.Set).List() - trigger := expandMonitorScheduledQueryRulesActionTrigger(triggerRaw) - - action := insights.AlertingAction{ - AznsAction: aznsAction, - Severity: insights.AlertSeverity(severity), - ThrottlingInMin: utils.Int32(int32(throttling)), - Trigger: trigger, - OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesAlertingAction, - } - - return &action -} - -func expandMonitorScheduledQueryRulesActionAznsAction(input []interface{}) *insights.AzNsActionGroup { - result := insights.AzNsActionGroup{} - - for _, item := range input { - v := item.(map[string]interface{}) - actionGroups := v["action_group"].(*schema.Set).List() - - result.ActionGroup = utils.ExpandStringSlice(actionGroups) - result.EmailSubject = utils.String(v["email_subject"].(string)) - result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) - } - - return &result -} - -func expandMonitorScheduledQueryRulesSchedule(d *schema.ResourceData) *insights.Schedule { - frequency := d.Get("frequency").(int) - timeWindow := d.Get("time_window").(int) - - schedule := insights.Schedule{ - FrequencyInMinutes: utils.Int32(int32(frequency)), - TimeWindowInMinutes: utils.Int32(int32(timeWindow)), - } - - return &schedule -} - -func expandMonitorScheduledQueryRulesActionMetricTrigger(input []interface{}) *insights.LogMetricTrigger { - if len(input) == 0 { - return nil - } - - result := insights.LogMetricTrigger{} - for _, item := range input { - v := item.(map[string]interface{}) - result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) - result.Threshold = utils.Float(v["threshold"].(float64)) - result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) - result.MetricColumn = utils.String(v["metric_column"].(string)) - } - - return &result -} - -func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { - authorizedResources := d.Get("authorized_resources").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - query := d.Get("query").(string) - - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResources), - DataSourceID: utils.String(dataSourceID), - Query: utils.String(query), - QueryType: insights.ResultCount, - } - - return &source -} - -func expandMonitorScheduledQueryRulesActionTrigger(input []interface{}) *insights.TriggerCondition { - result := insights.TriggerCondition{} - - for _, item := range input { - v := item.(map[string]interface{}) - metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() - - result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) - result.Threshold = utils.Float(v["threshold"].(float64)) - result.MetricTrigger = expandMonitorScheduledQueryRulesActionMetricTrigger(metricTriggerRaw) - } - - return &result -} - -func flattenAzureRmScheduledQueryRulesActionAznsAction(input *insights.AzNsActionGroup) []interface{} { - result := make([]interface{}, 0) - v := make(map[string]interface{}) - - if input != nil { - if input.ActionGroup != nil { - v["action_group"] = *input.ActionGroup - } - v["email_subject"] = input.EmailSubject - v["custom_webhook_payload"] = input.CustomWebhookPayload - } - result = append(result, v) - - return result -} - -func flattenAzureRmScheduledQueryRulesActionMetricTrigger(input *insights.LogMetricTrigger) []interface{} { - result := make(map[string]interface{}) - - if input == nil { - return []interface{}{} - } - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - result["metric_trigger_type"] = string(input.MetricTriggerType) - - if input.MetricColumn != nil { - result["metric_column"] = *input.MetricColumn - } - return []interface{}{result} -} - -func flattenAzureRmScheduledQueryRulesActionTrigger(input *insights.TriggerCondition) []interface{} { - result := make(map[string]interface{}) - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - if input.MetricTrigger != nil { - result["metric_trigger"] = flattenAzureRmScheduledQueryRulesActionMetricTrigger(input.MetricTrigger) - } - - return []interface{}{result} -} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go new file mode 100644 index 000000000000..1a66e95f8ef0 --- /dev/null +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -0,0 +1,336 @@ +package monitor + +import ( + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, + Read: resourceArmMonitorScheduledQueryRulesRead, + Update: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, + Delete: resourceArmMonitorScheduledQueryRulesDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.NoEmptyStrings, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "location": azure.SchemaLocation(), + + "authorized_resource_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, + }, + }, + "action": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action_group": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, + }, + }, + "custom_webhook_payload": { + Type: schema.TypeString, + Optional: true, + Default: "{}", + ValidateFunc: validation.ValidateJsonString, + }, + "email_subject": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "frequency": { + Type: schema.TypeInt, + Optional: true, + }, + "last_updated_time": { + Type: schema.TypeString, + Computed: true, + }, + "provisioning_state": { + Type: schema.TypeString, + Computed: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + }, + "query_type": { + Type: schema.TypeString, + Optional: true, + Default: "ResultCount", + ValidateFunc: validation.StringInSlice([]string{ + "ResultCount", + }, false), + }, + "severity": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntInSlice([]int{ + 0, + 1, + 2, + 3, + 4, + }), + }, + "throttling": { + Type: schema.TypeInt, + Optional: true, + }, + "time_window": { + Type: schema.TypeInt, + Optional: true, + }, + "trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_trigger": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metric_column": { + Type: schema.TypeString, + Required: true, + }, + "metric_trigger_type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "Consecutive", + "Total", + }, false), + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + }, + }, + }, + "operator": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "GreaterThan", + "LessThan", + "Equal", + }, false), + }, + "threshold": { + Type: schema.TypeFloat, + Required: true, + }, + }, + }, + }, + + "tags": tags.Schema(), + }, + } +} + +func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceData, meta interface{}) error { + var action insights.BasicAction + action = expandMonitorScheduledQueryRulesAlertingAction(d) + schedule := expandMonitorScheduledQueryRulesAlertSchedule(d) + + return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, schedule) +} + +func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { + alertActionRaw := d.Get("action").(*schema.Set).List() + alertAction := expandMonitorScheduledQueryRulesAlertAction(alertActionRaw) + severityRaw := d.Get("severity").(int) + severity := strconv.Itoa(severityRaw) + throttling := d.Get("throttling").(int) + + triggerRaw := d.Get("trigger").(*schema.Set).List() + trigger := expandMonitorScheduledQueryRulesAlertTrigger(triggerRaw) + + action := insights.AlertingAction{ + AznsAction: alertAction, + Severity: insights.AlertSeverity(severity), + ThrottlingInMin: utils.Int32(int32(throttling)), + Trigger: trigger, + OdataType: insights.OdataTypeMicrosoftWindowsAzureManagementMonitoringAlertsModelsMicrosoftAppInsightsNexusDataContractsResourcesScheduledQueryRulesAlertingAction, + } + + return &action +} + +func expandMonitorScheduledQueryRulesAlertAction(input []interface{}) *insights.AzNsActionGroup { + result := insights.AzNsActionGroup{} + + for _, item := range input { + v := item.(map[string]interface{}) + actionGroups := v["action_group"].(*schema.Set).List() + + result.ActionGroup = utils.ExpandStringSlice(actionGroups) + result.EmailSubject = utils.String(v["email_subject"].(string)) + result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesAlertMetricTrigger(input []interface{}) *insights.LogMetricTrigger { + if len(input) == 0 { + return nil + } + + result := insights.LogMetricTrigger{} + for _, item := range input { + v := item.(map[string]interface{}) + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) + result.MetricColumn = utils.String(v["metric_column"].(string)) + } + + return &result +} + +func expandMonitorScheduledQueryRulesAlertSchedule(d *schema.ResourceData) *insights.Schedule { + frequency := d.Get("frequency").(int) + timeWindow := d.Get("time_window").(int) + + schedule := insights.Schedule{ + FrequencyInMinutes: utils.Int32(int32(frequency)), + TimeWindowInMinutes: utils.Int32(int32(timeWindow)), + } + + return &schedule +} + +func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights.TriggerCondition { + result := insights.TriggerCondition{} + + for _, item := range input { + v := item.(map[string]interface{}) + metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() + + result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) + result.Threshold = utils.Float(v["threshold"].(float64)) + result.MetricTrigger = expandMonitorScheduledQueryRulesAlertMetricTrigger(metricTriggerRaw) + } + + return &result +} + +func flattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { + result := make([]interface{}, 0) + v := make(map[string]interface{}) + + if input != nil { + if input.ActionGroup != nil { + v["action_group"] = *input.ActionGroup + } + v["email_subject"] = input.EmailSubject + v["custom_webhook_payload"] = input.CustomWebhookPayload + } + result = append(result, v) + + return result +} + +func flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + result["metric_trigger_type"] = string(input.MetricTriggerType) + + if input.MetricColumn != nil { + result["metric_column"] = *input.MetricColumn + } + return []interface{}{result} +} + +func flattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { + result := make(map[string]interface{}) + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + if input.MetricTrigger != nil { + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) + } + + return []interface{}{result} +} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index 1167d81da80e..a25ee0535b20 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -1,30 +1,23 @@ package monitor import ( - "fmt" - "log" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ Create: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesLogRead, + Read: resourceArmMonitorScheduledQueryRulesRead, Update: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesLogDelete, + Delete: resourceArmMonitorScheduledQueryRulesDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -48,41 +41,18 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "location": azure.SchemaLocation(), - "authorized_resources": { + "authorized_resource_ids": { Type: schema.TypeSet, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "azns_action": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "action_group": { - Type: schema.TypeSet, - Required: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - "custom_webhook_payload": { - Type: schema.TypeString, - Optional: true, - Default: "{}", - ValidateFunc: validation.ValidateJsonString, - }, - "email_subject": { - Type: schema.TypeString, - Optional: true, - }, - }, + Type: schema.TypeString, + ValidateFunc: azure.ValidateResourceID, }, }, + "criteria": { Type: schema.TypeSet, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "dimension": { @@ -91,12 +61,14 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, "operator": { Type: schema.TypeString, - Required: true, + Optional: true, + Default: "Include", ValidateFunc: validation.StringInSlice([]string{ "Include", }, false), @@ -105,15 +77,17 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeList, Required: true, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, }, }, }, }, }, "metric_name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.NoEmptyStrings, }, }, }, @@ -132,10 +106,6 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Optional: true, Default: true, }, - "frequency": { - Type: schema.TypeInt, - Optional: true, - }, "last_updated_time": { Type: schema.TypeString, Computed: true, @@ -144,92 +114,6 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "query": { - Type: schema.TypeString, - Optional: true, - }, - "query_type": { - Type: schema.TypeString, - Optional: true, - Default: "ResultCount", - ValidateFunc: validation.StringInSlice([]string{ - "ResultCount", - }, false), - }, - "severity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntInSlice([]int{ - 0, - 1, - 2, - 3, - 4, - }), - }, - "throttling": { - Type: schema.TypeInt, - Optional: true, - }, - "time_window": { - Type: schema.TypeInt, - Optional: true, - }, - "trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_trigger": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "metric_column": { - Type: schema.TypeString, - Required: true, - }, - "metric_trigger_type": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "Consecutive", - "Total", - }, false), - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - ValidateFunc: validation.NoZeroValues, - }, - }, - }, - }, - "operator": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validation.StringInSlice([]string{ - "GreaterThan", - "LessThan", - "Equal", - }, false), - }, - "threshold": { - Type: schema.TypeFloat, - Required: true, - }, - }, - }, - }, "tags": tags.Schema(), }, @@ -237,165 +121,9 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { } func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_log", *existing.ID) - } - } - - description := d.Get("description").(string) - enabledRaw := d.Get("enabled").(bool) - - enabled := insights.True - if !enabledRaw { - enabled = insights.False - } - - location := azure.NormalizeLocation(d.Get("location")) - - var action insights.BasicAction - action = expandMonitorScheduledQueryRulesLogToMetricAction(d) - source := expandMonitorScheduledQueryRulesSource(d) - schedule := expandMonitorScheduledQueryRulesSchedule(d) + action := expandMonitorScheduledQueryRulesLogToMetricAction(d) - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - - parameters := insights.LogSearchRuleResource{ - Location: utils.String(location), - LogSearchRule: &insights.LogSearchRule{ - Description: utils.String(description), - Enabled: enabled, - Source: source, - Schedule: schedule, - Action: action, - }, - Tags: expandedTags, - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - read, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return err - } - if read.ID == nil { - return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) - } - d.SetId(*read.ID) - - return resourceArmMonitorScheduledQueryRulesLogRead(d, meta) -} - -func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) - d.SetId("") - return nil - } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - d.Set("description", resp.Description) - - switch action := resp.Action.(type) { - case insights.LogToMetricAction: - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resources", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { - if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - } - - return nil + return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, nil) } func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insights.Criteria { @@ -421,6 +149,19 @@ func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insight return &criteria } +func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + + return &source +} + func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { criteriaRaw := d.Get("criteria").(*schema.Set).List() criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go similarity index 65% rename from azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go rename to azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index 875fdaa76202..8e9109393791 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_action_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -9,25 +9,8 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - ), - }, - }, - }) -} - func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -44,7 +27,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin } func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -60,59 +43,12 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou }) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - action_type = "LogToMetric" - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = [""] - } - } -} - -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) -} - func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -130,13 +66,12 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true - action_type = "Alerting" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" data_source_id = "${azurerm_log_analytics_workspace.test.id}" @@ -146,7 +81,7 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" } @@ -163,8 +98,8 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" +data "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) @@ -175,7 +110,7 @@ func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -201,24 +136,23 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestSqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true - action_type = "Alerting" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" data_source_id = "${azurerm_log_analytics_workspace.test.id}" query_type = "ResultCount" - authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] frequency = 60 time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" } @@ -235,8 +169,8 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { } } -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" +data "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index 875fdaa76202..bb4b7e3c04c0 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -3,14 +3,13 @@ package tests import ( "fmt" "testing" - "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") + data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -26,44 +25,10 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes }) } -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - ), - }, - }, - }) -} - -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules", "test") - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { acceptance.PreCheck(t) }, - Providers: acceptance.SupportedProviders, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet(data.ResourceName, "id"), - ), - }, - }, - }) -} - func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -80,13 +45,12 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules" "test" { +resource "azurerm_monitor_scheduled_query_rules_log" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" + location = "${azurerm_resource_group.test.location}" description = "test log to metric action" enabled = true - action_type = "LogToMetric" data_source_id = "${azurerm_application_insights.test.id}" @@ -95,149 +59,14 @@ resource "azurerm_monitor_scheduled_query_rules" "test" { dimension { name = "InstanceName" operator = "Include" - values = [""] + values = ["50"] } } } -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" +data "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } - -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { - ts := time.Now().Format(time.RFC3339) - - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - action_type = "Alerting" - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - - frequency = 60 - time_window = 60 - - severity = 3 - azns_action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} - -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) -} - -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { - ts := time.Now().Format(time.RFC3339) - - return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_log_analytics_workspace" "test2" { - name = "acctestWorkspace2-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules" "test" { - name = "acctestSqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - action_type = "Alerting" - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - authorized_resources = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] - - frequency = 60 - time_window = 60 - - severity = 3 - azns_action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} - -data "azurerm_monitor_scheduled_query_rules" "test" { - name = "${azurerm_monitor_scheduled_query_rules.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) -} diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go similarity index 84% rename from azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go rename to azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index 1bb822ff80a2..2947388733a5 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_action_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -13,7 +13,7 @@ import ( ) func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -36,7 +36,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { } func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_action", "test") + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -63,7 +63,7 @@ func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.Tes return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -80,13 +80,12 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules_action" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action" enabled = true - action_type = "Alerting" data_source_id = "${azurerm_application_insights.test.id}" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" @@ -96,7 +95,7 @@ resource "azurerm_monitor_scheduled_query_rules_action" "test" { time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" custom_webhook_payload = "{}" @@ -119,7 +118,7 @@ resource "azurerm_monitor_scheduled_query_rules_action" "test" { func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -144,24 +143,23 @@ resource "azurerm_monitor_action_group" "test" { short_name = "acctestag" } -resource "azurerm_monitor_scheduled_query_rules_action" "test" { +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" description = "test alerting action cross-resource" enabled = true - action_type = "Alerting" - authorized_resources = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] - data_source_id = "${azurerm_application_insights.test.id}" - query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] + data_source_id = "${azurerm_application_insights.test.id}" + query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) query_type = "ResultCount" frequency = 60 time_window = 60 severity = 3 - azns_action { + action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" } @@ -179,7 +177,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext for _, rs := range s.RootModule().Resources { - if rs.Type != "azurerm_monitor_scheduled_query_rules_action" { + if rs.Type != "azurerm_monitor_scheduled_query_rules_alert" { continue } @@ -200,7 +198,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error return nil } -func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resource.TestCheckFunc { +func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[resourceName] diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 069f41ae89e7..91e751dcf4b0 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -37,7 +37,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" + name = "acctestRG-monitor-%d" location = "%s" } @@ -60,7 +60,6 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { location = "${azurerm_resource_group.test.location}" description = "test log to metric action" enabled = true - action_type = "LogToMetric" data_source_id = "${azurerm_application_insights.test.id}" @@ -69,14 +68,14 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { dimension { name = "InstanceName" operator = "Include" - values = [""] + values = ["50"] } } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { +func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index 4d92728a8984..f44dbf8b8750 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -32,8 +32,8 @@ output "query_rule_id" { ## Attributes Reference * `id` - The ID of the Scheduled Query Rule. -* `azns_action` - An `azns_action` block as defined below. -* `authorized_resources` - List of Resource IDs referred into query. +* `action` - An `action` block as defined below. +* `authorized_resource_ids` - List of Resource IDs referred into query. * `data_source_id` - The resource uri over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this scheduled query rule is enabled. @@ -47,9 +47,9 @@ output "query_rule_id" { --- -* `azns_action` supports the following: +* `action` supports the following: -* `action_group` - (Optional) List of action group reference resource IDs. +* `action_group` - List of action group reference resource IDs. * `custom_webhook_payload` - Custom payload to be sent for all webhook URI in Azure action group. * `email_subject` - Custom subject override for all email ids in Azure action group. @@ -57,15 +57,15 @@ output "query_rule_id" { `metricTrigger` supports the following: -* `metricColumn` - (Required) Evaluation of metric on a particular column. -* `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. -* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) The threshold of the metric trigger. +* `metricColumn` - Evaluation of metric on a particular column. +* `metricTriggerType` - Metric Trigger Type - 'Consecutive' or 'Total'. +* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - The threshold of the metric trigger. --- `trigger` supports the following: -* `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. -* `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) Result or count threshold based on which rule should be triggered. +* `metricTrigger` - A `metricTrigger` block as defined above. Trigger condition for metric query rule. +* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `threshold` - Result or count threshold based on which rule should be triggered. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index a29912472b68..a16f97be51e5 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -42,13 +42,13 @@ output "query_rule_id" { `criteria` supports the following: -* `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. +* `dimension` - A `dimension` block as defined below. +* `metric_name` - Name of the metric. --- `dimension` supports the following: -* `name` - (Required) Name of the dimension. -* `operator` - (Required) Operator for dimension values, - 'Include'. -* `values` - (Required) List of dimension values. +* `name` - Name of the dimension. +* `operator` - Operator for dimension values, - 'Include'. +* `values` - List of dimension values. diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index d78cbf5c4eec..ff4487816ae6 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -40,7 +40,7 @@ resource "azurerm_scheduled_query_rule_alert" "example" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - azns_action { + action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" @@ -71,9 +71,9 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - authorized_resources = [azurerm_application_insights.example.id, + authorized_resource_ids = [azurerm_application_insights.example.id, azurerm_log_analytics_workspace.example.id] - azns_action { + action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" @@ -99,8 +99,8 @@ The following arguments are supported: * `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. -* `authorized_resources` - (Optional) List of Resource IDs referred into query. -* `azns_action` - (Optional) An `azns_action` block as defined below. +* `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. +* `action` - (Optional) An `action` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. @@ -114,9 +114,9 @@ The following arguments are supported: --- -* `azns_action` supports the following: +* `action` supports the following: -* `action_group` - (Optional) List of action group reference resource IDs. +* `action_group` - (Required) List of action group reference resource IDs. * `custom_webhook_payload` - (Optional) Custom payload to be sent for all webhook payloads in alerting action. * `email_subject` - (Optional) Custom subject override for all email ids in Azure action group. From 7220ba410f7ac07de3ff450d10e9803a79dbfa79 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 11:58:20 -0600 Subject: [PATCH 13/25] Fix lint issues and minor typos --- ...ce_arm_monitor_scheduled_query_rules_alert.go | 3 +-- ...urce_arm_monitor_scheduled_query_rules_log.go | 13 ------------- ...m_monitor_scheduled_query_rules_alert_test.go | 16 ++++++++-------- ...arm_monitor_scheduled_query_rules_log_test.go | 12 ++++++------ 4 files changed, 15 insertions(+), 29 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 1a66e95f8ef0..98bda4dbcd17 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -195,8 +195,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { } func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceData, meta interface{}) error { - var action insights.BasicAction - action = expandMonitorScheduledQueryRulesAlertingAction(d) + action := expandMonitorScheduledQueryRulesAlertingAction(d) schedule := expandMonitorScheduledQueryRulesAlertSchedule(d) return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, schedule) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index a25ee0535b20..65c464e01f3a 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -149,19 +149,6 @@ func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insight return &criteria } -func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - QueryType: insights.ResultCount, - } - - return &source -} - func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { criteriaRaw := d.Get("criteria").(*schema.Set).List() criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index 2947388733a5..a16c0b8a5c53 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -18,12 +18,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMMonitorScheduledQueryRules_alertingAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, { @@ -41,12 +41,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, { @@ -172,7 +172,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error { +func testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -191,7 +191,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesDestroy(s *terraform.State) error } if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + return fmt.Errorf("Scheduled Query Rule still exists:\n%#v", resp) } } @@ -209,7 +209,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(resourceName string) name := rs.Primary.Attributes["name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for Activity Log Alert Instance: %s", name) + return fmt.Errorf("Bad: no resource group found in state for Scheduled Query Rule Instance: %s", name) } client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient @@ -221,7 +221,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(resourceName string) } if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + return fmt.Errorf("Bad: Scheduled Query Rule Instance %q (resource group: %q) does not exist", name, resourceGroup) } return nil diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 91e751dcf4b0..8dd720c71463 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -17,12 +17,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, Steps: []resource.TestStep{ { Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), ), }, { @@ -94,14 +94,14 @@ func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) er } if resp.StatusCode != http.StatusNotFound { - return fmt.Errorf("Activity log alert still exists:\n%#v", resp) + return fmt.Errorf("Scheduled Query Rule still exists:\n%#v", resp) } } return nil } -func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resource.TestCheckFunc { +func testCheckAzureRMMonitorScheduledQueryRulesLogExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[resourceName] @@ -112,7 +112,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resou name := rs.Primary.Attributes["name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for Activity Log Alert Instance: %s", name) + return fmt.Errorf("Bad: no resource group found in state for Scheduled Query Rule Instance: %s", name) } client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient @@ -124,7 +124,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesExists(resourceName string) resou } if resp.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: Activity Log Alert Instance %q (resource group: %q) does not exist", name, resourceGroup) + return fmt.Errorf("Bad: Scheduled Query Rule Instance %q (resource group: %q) does not exist", name, resourceGroup) } return nil From 3fa8441c0e0c0588574c3ad0eeff7e2383c09ca1 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 12:44:44 -0600 Subject: [PATCH 14/25] Fix lint issues #2 --- ...onitor_scheduled_query_rules_alert_test.go | 100 +++++++++--------- ..._monitor_scheduled_query_rules_log_test.go | 32 +++--- ...onitor_scheduled_query_rules_alert_test.go | 84 +++++++-------- ..._monitor_scheduled_query_rules_log_test.go | 28 ++--- ..._scheduled_query_rules_alert.html.markdown | 1 - ...or_scheduled_query_rules_log.html.markdown | 1 - ..._scheduled_query_rules_alert.html.markdown | 1 - ...or_scheduled_query_rules_log.html.markdown | 1 - 8 files changed, 122 insertions(+), 126 deletions(-) diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index 8e9109393791..4f4193912807 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -68,39 +68,39 @@ resource "azurerm_monitor_action_group" "test" { resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true + description = "test alerting action" + enabled = true - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" - frequency = 60 + frequency = 60 time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } } data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } @@ -140,38 +140,38 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestSqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true + description = "test alerting action" + enabled = true - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" + query_type = "ResultCount" + authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] - frequency = 60 + frequency = 60 time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } } data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index bb4b7e3c04c0..d25c6a7de355 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -46,27 +46,27 @@ resource "azurerm_monitor_action_group" "test" { } resource "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_application_insights.test.id}" - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = ["50"] - } - } + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = ["50"] + } + } } data "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" - resource_group_name = "${azurerm_resource_group.test.name}" + name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index a16c0b8a5c53..bedb59a88456 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -75,42 +75,42 @@ resource "azurerm_application_insights" "test" { } resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" + name = "acctestActionGroup-%d" resource_group_name = "${azurerm_resource_group.test.name}" short_name = "acctestag" } resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true + description = "test alerting action" + enabled = true - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_application_insights.test.id}" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - query_type = "ResultCount" + query_type = "ResultCount" - frequency = 60 + frequency = 60 time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - custom_webhook_payload = "{}" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + custom_webhook_payload = "{}" + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + metric_trigger { + operator = "GreaterThan" + threshold = 1 + metric_trigger_type = "Total" + metric_column = "TimeGenerated" + } + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } @@ -145,29 +145,29 @@ resource "azurerm_monitor_action_group" "test" { resource "azurerm_monitor_scheduled_query_rules_alert" "test" { name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test alerting action cross-resource" - enabled = true + description = "test alerting action cross-resource" + enabled = true - authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] - data_source_id = "${azurerm_application_insights.test.id}" - query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" + authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] + data_source_id = "${azurerm_application_insights.test.id}" + query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + query_type = "ResultCount" - frequency = 60 - time_window = 60 + frequency = 60 + time_window = 60 - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } + severity = 3 + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + email_subject = "Custom alert email subject" + } - trigger { - operator = "GreaterThan" - threshold = 5000 - } + trigger { + operator = "GreaterThan" + threshold = 5000 + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 8dd720c71463..2fc2efdd82f9 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -49,7 +49,7 @@ resource "azurerm_application_insights" "test" { } resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" + name = "acctestActionGroup-%d" resource_group_name = "${azurerm_resource_group.test.name}" short_name = "acctestag" } @@ -58,19 +58,19 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { name = "acctestsqr-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = ["50"] - } - } + description = "test log to metric action" + enabled = true + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = ["50"] + } + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) } diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index f44dbf8b8750..1998f0670646 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-alert" description: |- Get information about the specified AlertingAction Scheduled Query Rule. --- diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index a16f97be51e5..3633ba24d57f 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" -sidebar_current: "docs-azurerm-datasource-monitor-scheduled-query-rules-log" description: |- Get information about the specified LogToMetricAction Scheduled Query Rule. --- diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index ff4487816ae6..54324cbadc21 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-alert" description: |- Manages an AlertingAction Scheduled Query Rule within Azure Monitor --- diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index a5d6895fb301..29f6e8291c19 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -2,7 +2,6 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" -sidebar_current: "docs-azurerm-resource-monitor-scheduled-query-rules-log" description: |- Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor --- From d2a15de9c2b14b1e3c08bc7b3caa600cf03b2254 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 1 Feb 2020 13:12:41 -0600 Subject: [PATCH 15/25] Fix lint issues #3 --- ...ource_monitor_scheduled_query_rules_log.go | 1 - ...arm_monitor_scheduled_query_rules_alert.go | 2 +- ..._scheduled_query_rules_alert.html.markdown | 54 +++++++++---------- ...or_scheduled_query_rules_log.html.markdown | 24 ++++----- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index cd0853c6dc72..4a864f0f19f2 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -46,7 +46,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "name": { Type: schema.TypeString, Computed: true, - Elem: schema.TypeString, }, "operator": { Type: schema.TypeString, diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 98bda4dbcd17..cee4212d9823 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -67,7 +67,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Type: schema.TypeString, Optional: true, Default: "{}", - ValidateFunc: validation.ValidateJsonString, + ValidateFunc: validation.StringIsJSON, }, "email_subject": { Type: schema.TypeString, diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 54324cbadc21..19cdc7ee0148 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -35,26 +35,26 @@ resource "azurerm_log_analytics_workspace" "example" { # Example: Alerting Action resource "azurerm_scheduled_query_rule_alert" "example" { - name = format("%s-queryrule", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = format("%s-queryrule", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action example" - enabled = true - frequency = 5 - query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" - query_type = "ResultCount" - severity = 1 - time_window = 30 + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule Alerting Action example" + enabled = true + frequency = 5 + query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + query_type = "ResultCount" + severity = 1 + time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + threshold_operator = "GreaterThan" + threshold = 3 metric_trigger { operator = "GreaterThan" threshold = 1 @@ -66,28 +66,28 @@ resource "azurerm_scheduled_query_rule_alert" "example" { # Example: Alerting Action Cross-Resource resource "azurerm_scheduled_query_rule_alert" "example2" { - name = format("%s-queryrule2", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = format("%s-queryrule2", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name authorized_resource_ids = [azurerm_application_insights.example.id, - azurerm_log_analytics_workspace.example.id] + azurerm_log_analytics_workspace.example.id] action { action_group = [] email_subject = "Email Header" custom_webhook_payload = "{}" } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action cross-resource example" - enabled = true - frequency = 5 - query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" - severity = "1" - time_window = 30 + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule Alerting Action cross-resource example" + enabled = true + frequency = 5 + query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + query_type = "ResultCount" + severity = "1" + time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + threshold_operator = "GreaterThan" + threshold = 3 } } ``` diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 29f6e8291c19..7870b2c8d436 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -26,21 +26,21 @@ resource "azurerm_application_insights" "example" { } resource "azurerm_scheduled_query_rule_log" "example3" { - name = format("%s-queryrule3", var.prefix) - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name + name = format("%s-queryrule3", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name criteria { - metric_name = "Average_% Idle Time" - dimensions { - name = "InstanceName" - operator = "Include" - values = [""] - } + metric_name = "Average_% Idle Time" + dimensions { + name = "InstanceName" + operator = "Include" + values = [""] + } } - data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule LogToMetric example" - enabled = true + data_source_id = azurerm_application_insights.example.id + description = "Scheduled query rule LogToMetric example" + enabled = true } ``` From 04d4a12ae4639e2411b4c87bf53120266a2d58ad Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Wed, 5 Feb 2020 06:58:37 -0600 Subject: [PATCH 16/25] Fix documentation error --- .../r/monitor_scheduled_query_rules_alert.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 19cdc7ee0148..138e4fc9b472 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -53,8 +53,8 @@ resource "azurerm_scheduled_query_rule_alert" "example" { severity = 1 time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + operator = "GreaterThan" + threshold = 3 metric_trigger { operator = "GreaterThan" threshold = 1 @@ -86,8 +86,8 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { severity = "1" time_window = 30 trigger { - threshold_operator = "GreaterThan" - threshold = 3 + operator = "GreaterThan" + threshold = 3 } } ``` From 78ddff0e1414137012469a749202ec2032b9b6d8 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 8 Feb 2020 22:40:43 -0600 Subject: [PATCH 17/25] Add monitor helpers --- azurerm/helpers/azure/monitor.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 azurerm/helpers/azure/monitor.go diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/helpers/azure/monitor.go new file mode 100644 index 000000000000..7303e4d52ded --- /dev/null +++ b/azurerm/helpers/azure/monitor.go @@ -0,0 +1,32 @@ +package azure + +import ( + "fmt" + "strings" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +// ValidateThreshold checks that a threshold value is between 0 and 10000 +// and is a whole number. The azure-sdk-for-go expects this value to be a float64 +// but the user validation rules want an integer. +func ValidateThreshold(i interface{}, k string) (warnings []string, errors []error) { + v, ok := i.(float64) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %q to be float64", k)) + } + + if v != float64(int64(v)) { + errors = append(errors, fmt.Errorf("%q must be a whole number", k)) + } + + if v < 0 || v > 10000 { + errors = append(errors, fmt.Errorf("%q must be between 0 and 10000 inclusive", k)) + } + + return warnings, errors +} From e9ce2439140c8b164a832cecfad1e7de18e488c5 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sun, 9 Feb 2020 21:16:30 -0600 Subject: [PATCH 18/25] First pass address latest review --- azurerm/helpers/azure/monitor.go | 11 +- ...ta_source_monitor_scheduled_query_rules.go | 96 ------ ...rce_monitor_scheduled_query_rules_alert.go | 87 +++++- ...ource_monitor_scheduled_query_rules_log.go | 78 ++++- ...ource_arm_monitor_scheduled_query_rules.go | 207 ------------- ...arm_monitor_scheduled_query_rules_alert.go | 288 +++++++++++++++--- ...e_arm_monitor_scheduled_query_rules_log.go | 203 ++++++++++-- ...onitor_scheduled_query_rules_alert_test.go | 12 +- ..._monitor_scheduled_query_rules_log_test.go | 6 +- website/azurerm.erb | 16 + ..._scheduled_query_rules_alert.html.markdown | 26 +- ...or_scheduled_query_rules_log.html.markdown | 10 +- ..._scheduled_query_rules_alert.html.markdown | 20 +- ...or_scheduled_query_rules_log.html.markdown | 7 +- 14 files changed, 619 insertions(+), 448 deletions(-) delete mode 100644 azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go delete mode 100644 azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/helpers/azure/monitor.go index 7303e4d52ded..f5bf82a5bcf2 100644 --- a/azurerm/helpers/azure/monitor.go +++ b/azurerm/helpers/azure/monitor.go @@ -2,19 +2,12 @@ package azure import ( "fmt" - "strings" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) // ValidateThreshold checks that a threshold value is between 0 and 10000 // and is a whole number. The azure-sdk-for-go expects this value to be a float64 // but the user validation rules want an integer. -func ValidateThreshold(i interface{}, k string) (warnings []string, errors []error) { +func ValidateMonitorScheduledQueryRulesAlertThreshold(i interface{}, k string) (warnings []string, errors []error) { v, ok := i.(float64) if !ok { errors = append(errors, fmt.Errorf("expected type of %q to be float64", k)) @@ -25,7 +18,7 @@ func ValidateThreshold(i interface{}, k string) (warnings []string, errors []err } if v < 0 || v > 10000 { - errors = append(errors, fmt.Errorf("%q must be between 0 and 10000 inclusive", k)) + errors = append(errors, fmt.Errorf("%q must be between 0 and 10000 (inclusive)", k)) } return warnings, errors diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go deleted file mode 100644 index 72380eedcbd3..000000000000 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules.go +++ /dev/null @@ -1,96 +0,0 @@ -package monitor - -import ( - "fmt" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func dataSourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) - } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) - } - - d.SetId(*resp.ID) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - d.Set("description", resp.Description) - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - switch action := resp.Action.(type) { - case insights.AlertingAction: - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - case insights.LogToMetricAction: - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - return tags.FlattenAndSet(d, resp.Tags) -} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go index c7dc42763af8..cc535fed1452 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -1,16 +1,22 @@ package monitor import ( + "fmt" + "strconv" "time" + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesRead, + Read: dataSourceArmMonitorScheduledQueryRulesAlertRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -72,14 +78,6 @@ func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Type: schema.TypeInt, Computed: true, }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, "query": { Type: schema.TypeString, Computed: true, @@ -145,3 +143,74 @@ func dataSourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, } } + +func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + action, ok := resp.Action.(insights.AlertingAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index 4a864f0f19f2..bad7e1f79797 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -1,16 +1,21 @@ package monitor import ( + "fmt" "time" + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ - Read: dataSourceArmMonitorScheduledQueryRulesRead, + Read: dataSourceArmMonitorScheduledQueryRulesLogRead, Timeouts: &schema.ResourceTimeout{ Read: schema.DefaultTimeout(5 * time.Minute), @@ -80,18 +85,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, - "query": { - Type: schema.TypeString, - Computed: true, - }, "query_type": { Type: schema.TypeString, Computed: true, @@ -101,3 +94,62 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { }, } } + +func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + } + return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + } + + d.SetId(*resp.ID) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + d.Set("description", resp.Description) + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + action, ok := resp.Action.(insights.LogToMetricAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + d.Set("query_type", string(source.QueryType)) + } + + return tags.FlattenAndSet(d, resp.Tags) +} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go deleted file mode 100644 index b7661870314a..000000000000 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules.go +++ /dev/null @@ -1,207 +0,0 @@ -package monitor - -import ( - "fmt" - "log" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" - "github.com/hashicorp/go-azure-helpers/response" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" -) - -func resourceArmMonitorScheduledQueryRulesCreateUpdate(d *schema.ResourceData, meta interface{}, action insights.BasicAction, schedule *insights.Schedule) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) - defer cancel() - - name := d.Get("name").(string) - resourceGroup := d.Get("resource_group_name").(string) - - if features.ShouldResourcesBeImported() && d.IsNewResource() { - existing, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) - } - } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) - } - } - - description := d.Get("description").(string) - enabledRaw := d.Get("enabled").(bool) - - enabled := insights.True - if !enabledRaw { - enabled = insights.False - } - - location := azure.NormalizeLocation(d.Get("location")) - - source := expandMonitorScheduledQueryRulesSource(d) - - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - - parameters := insights.LogSearchRuleResource{ - Location: utils.String(location), - LogSearchRule: &insights.LogSearchRule{ - Description: utils.String(description), - Enabled: enabled, - Source: source, - Schedule: schedule, - Action: action, - }, - Tags: expandedTags, - } - - if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - read, err := client.Get(ctx, resourceGroup, name) - if err != nil { - return err - } - if read.ID == nil { - return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) - } - d.SetId(*read.ID) - - return resourceArmMonitorScheduledQueryRulesRead(d, meta) -} - -func resourceArmMonitorScheduledQueryRulesRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - resp, err := client.Get(ctx, resourceGroup, name) - if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) - d.SetId("") - return nil - } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - - d.Set("name", name) - d.Set("resource_group_name", resourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - if lastUpdated := resp.LastUpdatedTime; lastUpdated != nil { - d.Set("last_updated_time", lastUpdated.Format(time.RFC3339)) - } - d.Set("provisioning_state", resp.ProvisioningState) - - if resp.Enabled == insights.True { - d.Set("enabled", true) - } else { - d.Set("enabled", false) - } - - d.Set("description", resp.Description) - - switch action := resp.Action.(type) { - case insights.AlertingAction: - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { - return fmt.Errorf("Error setting `action`: %+v", err) - } - severity, err := strconv.Atoi(string(action.Severity)) - if err != nil { - return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) - } - d.Set("severity", severity) - d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { - return fmt.Errorf("Error setting `trigger`: %+v", err) - } - case insights.LogToMetricAction: - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { - return fmt.Errorf("Error setting `criteria`: %+v", err) - } - default: - return fmt.Errorf("Unknown action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) - } - - if schedule := resp.Schedule; schedule != nil { - if schedule.FrequencyInMinutes != nil { - d.Set("frequency", schedule.FrequencyInMinutes) - } - if schedule.TimeWindowInMinutes != nil { - d.Set("time_window", schedule.TimeWindowInMinutes) - } - } - - if source := resp.Source; source != nil { - if source.AuthorizedResources != nil { - d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) - } - if source.DataSourceID != nil { - d.Set("data_source_id", source.DataSourceID) - } - if source.Query != nil { - d.Set("query", source.Query) - } - d.Set("query_type", string(source.QueryType)) - } - - return tags.FlattenAndSet(d, resp.Tags) -} - -func resourceArmMonitorScheduledQueryRulesDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient - ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) - defer cancel() - - id, err := azure.ParseAzureResourceID(d.Id()) - if err != nil { - return err - } - resourceGroup := id.ResourceGroup - name := id.Path["scheduledqueryrules"] - - if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { - if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) - } - } - - return nil -} - -func expandMonitorScheduledQueryRulesSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - query, ok := d.Get("query").(string) - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - QueryType: insights.ResultCount, - } - if ok { - source.Query = utils.String(query) - } - - return &source -} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index cee4212d9823..3fb0fa6c8317 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -1,24 +1,30 @@ package monitor import ( + "fmt" + "log" "strconv" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { return &schema.Resource{ Create: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesRead, + Read: resourceArmMonitorScheduledQueryRulesAlertRead, Update: resourceArmMonitorScheduledQueryRulesAlertCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesDelete, + Delete: resourceArmMonitorScheduledQueryRulesAlertDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -35,7 +41,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringDoesNotContainAny("<>*%&:\\?+/"), }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -70,8 +76,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { ValidateFunc: validation.StringIsJSON, }, "email_subject": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -82,8 +89,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { ValidateFunc: azure.ValidateResourceID, }, "description": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 4096), }, "enabled": { Type: schema.TypeBool, @@ -91,20 +99,14 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Default: true, }, "frequency": { - Type: schema.TypeInt, - Optional: true, - }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(5, 1440), }, "query": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "query_type": { Type: schema.TypeString, @@ -115,27 +117,23 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, false), }, "severity": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntInSlice([]int{ - 0, - 1, - 2, - 3, - 4, - }), + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 4), }, "throttling": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 10000), }, "time_window": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(5, 2880), }, "trigger": { Type: schema.TypeSet, - Optional: true, + Required: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_trigger": { @@ -144,8 +142,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_column": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, }, "metric_trigger_type": { Type: schema.TypeString, @@ -167,7 +166,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { "threshold": { Type: schema.TypeFloat, Required: true, - ValidateFunc: validation.NoZeroValues, + ValidateFunc: azure.ValidateMonitorScheduledQueryRulesAlertThreshold, }, }, }, @@ -182,8 +181,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, false), }, "threshold": { - Type: schema.TypeFloat, - Required: true, + Type: schema.TypeFloat, + Required: true, + ValidateFunc: azure.ValidateMonitorScheduledQueryRulesAlertThreshold, }, }, }, @@ -197,8 +197,170 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceData, meta interface{}) error { action := expandMonitorScheduledQueryRulesAlertingAction(d) schedule := expandMonitorScheduledQueryRulesAlertSchedule(d) + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if *schedule.TimeWindowInMinutes < *schedule.FrequencyInMinutes { + return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): time_window must be greater than or equal to frequency", name, resourceGroup) + } + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + source := expandMonitorScheduledQueryRulesAlertSource(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Schedule: schedule, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesAlertRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + action, ok := resp.Action.(insights.AlertingAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + return fmt.Errorf("Error setting `action`: %+v", err) + } + severity, err := strconv.Atoi(string(action.Severity)) + if err != nil { + return fmt.Errorf("Error converting action.Severity %q in query rule %q to int (resource group %q): %+v", action.Severity, name, resourceGroup, err) + } + d.Set("severity", severity) + d.Set("throttling", action.ThrottlingInMin) + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + return fmt.Errorf("Error setting `trigger`: %+v", err) + } + + if schedule := resp.Schedule; schedule != nil { + if schedule.FrequencyInMinutes != nil { + d.Set("frequency", schedule.FrequencyInMinutes) + } + if schedule.TimeWindowInMinutes != nil { + d.Set("time_window", schedule.TimeWindowInMinutes) + } + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + if source.Query != nil { + d.Set("query", source.Query) + } + d.Set("query_type", string(source.QueryType)) + } - return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, schedule) + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesAlertDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil } func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { @@ -225,10 +387,19 @@ func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *ins func expandMonitorScheduledQueryRulesAlertAction(input []interface{}) *insights.AzNsActionGroup { result := insights.AzNsActionGroup{} + if len(input) == 0 { + return &result + } for _, item := range input { - v := item.(map[string]interface{}) - actionGroups := v["action_group"].(*schema.Set).List() + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } + actionGroups := v["action_group"].(*schema.Set).List() result.ActionGroup = utils.ExpandStringSlice(actionGroups) result.EmailSubject = utils.String(v["email_subject"].(string)) result.CustomWebhookPayload = utils.String(v["custom_webhook_payload"].(string)) @@ -244,7 +415,13 @@ func expandMonitorScheduledQueryRulesAlertMetricTrigger(input []interface{}) *in result := insights.LogMetricTrigger{} for _, item := range input { - v := item.(map[string]interface{}) + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) result.Threshold = utils.Float(v["threshold"].(float64)) result.MetricTriggerType = insights.MetricTriggerType(v["metric_trigger_type"].(string)) @@ -266,11 +443,34 @@ func expandMonitorScheduledQueryRulesAlertSchedule(d *schema.ResourceData) *insi return &schedule } +func expandMonitorScheduledQueryRulesAlertSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query := d.Get("query").(string) + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + Query: utils.String(query), + QueryType: insights.ResultCount, + } + + return &source +} + func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights.TriggerCondition { result := insights.TriggerCondition{} + if len(input) == 0 { + return &result + } for _, item := range input { - v := item.(map[string]interface{}) + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index 65c464e01f3a..f9537f6a7306 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -1,23 +1,29 @@ package monitor import ( + "fmt" + "log" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { return &schema.Resource{ Create: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Read: resourceArmMonitorScheduledQueryRulesRead, + Read: resourceArmMonitorScheduledQueryRulesLogRead, Update: resourceArmMonitorScheduledQueryRulesLogCreateUpdate, - Delete: resourceArmMonitorScheduledQueryRulesDelete, + Delete: resourceArmMonitorScheduledQueryRulesLogDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -34,7 +40,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringDoesNotContainAny("<>*%&:\\?+/"), }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -63,7 +69,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "name": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringIsNotEmpty, }, "operator": { Type: schema.TypeString, @@ -78,7 +84,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -87,7 +93,7 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { "metric_name": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.NoEmptyStrings, + ValidateFunc: validation.StringIsNotEmpty, }, }, }, @@ -98,22 +104,15 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { ValidateFunc: azure.ValidateResourceID, }, "description": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 4096), }, "enabled": { Type: schema.TypeBool, Optional: true, Default: true, }, - "last_updated_time": { - Type: schema.TypeString, - Computed: true, - }, - "provisioning_state": { - Type: schema.TypeString, - Computed: true, - }, "tags": tags.Schema(), }, @@ -123,17 +122,169 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData, meta interface{}) error { action := expandMonitorScheduledQueryRulesLogToMetricAction(d) - return resourceArmMonitorScheduledQueryRulesCreateUpdate(d, meta, action, nil) + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Monitor Scheduled Query Rules %q (Resource Group %q): %s", name, resourceGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_monitor_scheduled_query_rules_alert", *existing.ID) + } + } + + description := d.Get("description").(string) + enabledRaw := d.Get("enabled").(bool) + + enabled := insights.True + if !enabledRaw { + enabled = insights.False + } + + location := azure.NormalizeLocation(d.Get("location")) + + source := expandMonitorScheduledQueryRulesLogSource(d) + + t := d.Get("tags").(map[string]interface{}) + expandedTags := tags.Expand(t) + + parameters := insights.LogSearchRuleResource{ + Location: utils.String(location), + LogSearchRule: &insights.LogSearchRule{ + Description: utils.String(description), + Enabled: enabled, + Source: source, + Action: action, + }, + Tags: expandedTags, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { + return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Scheduled query rule %q (resource group %q) ID is empty", name, resourceGroup) + } + d.SetId(*read.ID) + + return resourceArmMonitorScheduledQueryRulesLogRead(d, meta) +} + +func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + d.SetId("") + return nil + } + return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + if location := resp.Location; location != nil { + d.Set("location", azure.NormalizeLocation(*location)) + } + + if resp.Enabled == insights.True { + d.Set("enabled", true) + } else { + d.Set("enabled", false) + } + + d.Set("description", resp.Description) + + action, ok := resp.Action.(insights.LogToMetricAction) + if !ok { + return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + } + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + return fmt.Errorf("Error setting `criteria`: %+v", err) + } + + if source := resp.Source; source != nil { + if source.AuthorizedResources != nil { + d.Set("authorized_resource_ids", utils.FlattenStringSlice(source.AuthorizedResources)) + } + if source.DataSourceID != nil { + d.Set("data_source_id", source.DataSourceID) + } + } + + return tags.FlattenAndSet(d, resp.Tags) +} + +func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["scheduledqueryrules"] + + if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { + if !response.WasNotFound(resp.Response) { + return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + } + } + + return nil } func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insights.Criteria { criteria := make([]insights.Criteria, 0) + if len(input) == 0 { + return &criteria + } + for _, item := range input { - v := item.(map[string]interface{}) + if item == nil { + continue + } + v, ok := item.(map[string]interface{}) + if !ok { + continue + } dimensions := make([]insights.Dimension, 0) for _, dimension := range v["dimension"].(*schema.Set).List() { - dVal := dimension.(map[string]interface{}) + if dimension == nil { + continue + } + dVal, ok := dimension.(map[string]interface{}) + if !ok { + continue + } dimensions = append(dimensions, insights.Dimension{ Name: utils.String(dVal["name"].(string)), Operator: utils.String(dVal["operator"].(string)), @@ -161,6 +312,18 @@ func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) * return &action } +func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + + return &source +} + func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { result := make([]interface{}, 0) diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index bedb59a88456..a558a5359366 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -26,11 +26,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) } @@ -49,11 +45,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 2fc2efdd82f9..0706ca581078 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -25,11 +25,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), ), }, - { - ResourceName: data.ResourceName, - ImportState: true, - ImportStateVerify: true, - }, + data.ImportStep(), }, }) } diff --git a/website/azurerm.erb b/website/azurerm.erb index f9251797f18b..7553baf65cf4 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -298,6 +298,14 @@ azurerm_monitor_log_profile +
  • + azurerm_monitor_scheduled_query_rules_alert +
  • + +
  • + azurerm_monitor_scheduled_query_rules_log +
  • +
  • azurerm_mssql_elasticpool
  • @@ -1703,6 +1711,14 @@
  • azurerm_metric_alertrule
  • + +
  • + azurerm_monitor_scheduled_query_rules_alert +
  • + +
  • + azurerm_monitor_scheduled_query_rules_log +
  • diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index 1998f0670646..7e513bf3c885 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -26,23 +26,23 @@ output "query_rule_id" { ## Argument Reference * `name` - (Required) Specifies the name of the Scheduled Query Rule. -* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. +* `resource_group_name` - (Required) Specifies the name of the resource group where the Scheduled Query Rule is located. ## Attributes Reference * `id` - The ID of the Scheduled Query Rule. * `action` - An `action` block as defined below. * `authorized_resource_ids` - List of Resource IDs referred into query. -* `data_source_id` - The resource uri over which log search query is to be run. +* `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this scheduled query rule is enabled. -* `frequency` - Frequency (in minutes) at which rule condition should be evaluated. -* `query` - Log search query. Required for action type - `alerting_action`. +* `frequency` - Frequency at which rule condition should be evaluated. +* `query` - Log search query. * `query_type` - Must equal "ResultCount". -* `time_window` - Time window for which data needs to be fetched for query (should be greater than or equal to frequency_in_minutes). -* `severity` - Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. -* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. -* `trigger` - A `trigger` block as defined below. The condition that results in the alert rule being run. +* `time_window` - Time window for which data needs to be fetched for query. +* `severity` - Severity of the alert. +* `throttling` - Time for which alerts should be throttled or suppressed. +* `trigger` - A `trigger` block as defined below. --- @@ -50,21 +50,21 @@ output "query_rule_id" { * `action_group` - List of action group reference resource IDs. * `custom_webhook_payload` - Custom payload to be sent for all webhook URI in Azure action group. -* `email_subject` - Custom subject override for all email ids in Azure action group. +* `email_subject` - Custom subject override for all email IDs in Azure action group. --- `metricTrigger` supports the following: * `metricColumn` - Evaluation of metric on a particular column. -* `metricTriggerType` - Metric Trigger Type - 'Consecutive' or 'Total'. -* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `metricTriggerType` - The metric trigger type. +* `operator` - Evaluation operation for rule. * `threshold` - The threshold of the metric trigger. --- `trigger` supports the following: -* `metricTrigger` - A `metricTrigger` block as defined above. Trigger condition for metric query rule. -* `operator` - Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. +* `metricTrigger` - A `metricTrigger` block as defined above. +* `operator` - Evaluation operation for rule. * `threshold` - Result or count threshold based on which rule should be triggered. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index 3633ba24d57f..af8890e478d2 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -26,16 +26,16 @@ output "query_rule_id" { ## Argument Reference * `name` - (Required) Specifies the name of the Scheduled Query Rule. -* `resource_group_name` - (Required) Specifies the name of the resource group the Scheduled Query Rule is located in. +* `resource_group_name` - (Required) Specifies the name of the resource group where the Scheduled Query Rule is located. ## Attributes Reference * `id` - The ID of the Scheduled Query Rule. * `criteria` - A `criteria` block as defined below. -* `data_source_id` - The resource uri over which log search query is to be run. +* `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. -* `enabled` - Whether this scheduled query rule is enabled. -* `throttling` - Time (in minutes) for which Alerts should be throttled or suppressed. +* `enabled` - Whether this Scheduled Query Rule is enabled. +* `throttling` - Time for which alerts should be throttled or suppressed. --- @@ -49,5 +49,5 @@ output "query_rule_id" { `dimension` supports the following: * `name` - Name of the dimension. -* `operator` - Operator for dimension values, - 'Include'. +* `operator` - Operator for dimension values. * `values` - List of dimension values. diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 138e4fc9b472..647252ecd1e2 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -49,7 +49,6 @@ resource "azurerm_scheduled_query_rule_alert" "example" { enabled = true frequency = 5 query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" - query_type = "ResultCount" severity = 1 time_window = 30 trigger { @@ -82,7 +81,6 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { enabled = true frequency = 5 query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" severity = "1" time_window = 30 trigger { @@ -98,18 +96,16 @@ The following arguments are supported: * `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `data_source_id` - (Required) The resource URI over which log search query is to be run. +* `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. Values must be between 5 and 1440 (inclusive). +* `time_window` - (Required) Time window for which data needs to be fetched for query (must be greater than or equal to `frequency`). Values must be between 5 and 2880 (inclusive). +* `trigger` - (Required) The condition that results in the alert rule being run. * `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. * `action` - (Optional) An `action` block as defined below. -* `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. -* `query` - (Required) Log search query. -* `query_type` - (Required) Must equal "ResultCount" for now. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. -* `time_window` - (Required) Time window for which data needs to be fetched for query (should be greater than or equal to `frequency`). -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. -* `trigger` - (Required) The condition that results in the alert rule being run. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 (inclusive). --- @@ -126,7 +122,7 @@ The following arguments are supported: * `metricColumn` - (Required) Evaluation of metric on a particular column. * `metricTriggerType` - (Required) Metric Trigger Type - 'Consecutive' or 'Total'. * `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) The threshold of the metric trigger. +* `threshold` - (Required) The threshold of the metric trigger. Values must be between 0 and 10000 inclusive. --- @@ -134,15 +130,13 @@ The following arguments are supported: * `metricTrigger` - (Optional) A `metricTrigger` block as defined above. Trigger condition for metric query rule. * `operator` - (Required) Evaluation operation for rule - 'Equal', 'GreaterThan' or 'LessThan'. -* `threshold` - (Required) Result or count threshold based on which rule should be triggered. +* `threshold` - (Required) Result or count threshold based on which rule should be triggered. Values must be between 0 and 10000 inclusive. ## Attributes Reference The following attributes are exported: * `id` - The ID of the Scheduled Query Rule. -* `last_updated_time` - Last time the rule was updated in IS08601 format. -* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' ## Import diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 7870b2c8d436..48beb3b33359 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -54,14 +54,15 @@ The following arguments are supported: * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. * `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. +* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 ( +inclusive). --- `criteria` supports the following: * `dimension` - (Required) A `dimension` block as defined below. -* `metric_name` - (Required) Name of the metric. +* `metric_name` - (Required) Name of the metric. Supported metrics are listed in the Azure Monitor [Microsoft.OperationalInsights/workspaces](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-supported#microsoftoperationalinsightsworkspaces) metrics namespace. --- @@ -76,8 +77,6 @@ The following arguments are supported: The following attributes are exported: * `id` - The ID of the Scheduled Query Rule. -* `last_updated_time` - Last time the rule was updated in IS08601 format. -* `provisioning_state` - Provisioning state of the scheduled query rule. Possible values include: 'Succeeded', 'Deploying', 'Canceled', 'Failed' ## Import From 14d0825cc0c0f81d9d2ed1367d08dda729bafb4f Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 11 Feb 2020 10:07:10 -0600 Subject: [PATCH 19/25] Validate metric_trigger query; add example to docs --- ...arm_monitor_scheduled_query_rules_alert.go | 13 ++++++- ..._scheduled_query_rules_alert.html.markdown | 37 +++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 3fb0fa6c8317..6ea171c6cd89 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "strconv" + "strings" "time" "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" @@ -204,10 +205,20 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) - if *schedule.TimeWindowInMinutes < *schedule.FrequencyInMinutes { + frequency := d.Get("frequency").(int) + timeWindow := d.Get("time_window").(int) + if timeWindow < frequency { return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): time_window must be greater than or equal to frequency", name, resourceGroup) } + query := d.Get("query").(string) + _, ok := d.GetOk("metric_trigger") + if ok { + if !(strings.Contains(query, "summarize") && strings.Contains(query, "AggregatedValue") && strings.Contains(query, "bin")) { + return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): query must contain summarize, AggregatedValue, and bin when metric_trigger is specified", name, resourceGroup) + } + } + if features.ShouldResourcesBeImported() && d.IsNewResource() { existing, err := client.Get(ctx, resourceGroup, name) if err != nil { diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 647252ecd1e2..09cc58779091 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -33,7 +33,36 @@ resource "azurerm_log_analytics_workspace" "example" { retention_in_days = 30 } -# Example: Alerting Action + +# Example: Alerting Action with result count trigger +# Alert if more than three HTTP requests returned a >= 500 result code +# in the past 30 minutes +resource "azurerm_scheduled_query_rule_alert" "example" { + name = format("%s-queryrule", var.prefix) + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + + action { + action_group = [] + email_subject = "Email Header" + custom_webhook_payload = "{}" + } + data_source_id = azurerm_application_insights.example.id + description = "Result count trigger example - alert when total results cross threshold" + enabled = true + frequency = 5 + query = "requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + severity = 1 + time_window = 30 + trigger { + operator = "GreaterThan" + threshold = 3 + } +} + +# Example: Alerting Action with metric trigger +# Alert if more than three HTTP requests returned a >= 500 result code +# in the past 30 minutes that have the same operation (ie: GET /) resource "azurerm_scheduled_query_rule_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location @@ -45,10 +74,10 @@ resource "azurerm_scheduled_query_rule_alert" "example" { custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action example" + description = "Metric trigger example - query results grouped by metric; alert when results per metric_column cross threshold" enabled = true frequency = 5 - query = "requests | where status_code >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + query = "requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by operation_Name, bin(timestamp, 5m)" severity = 1 time_window = 30 trigger { @@ -58,7 +87,7 @@ resource "azurerm_scheduled_query_rule_alert" "example" { operator = "GreaterThan" threshold = 1 metric_trigger_type = "Total" - metric_column = "timestamp" + metric_column = "operation_Name" } } } From 651c41fe20749876087ada46c328c5d33201fb8c Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 15 Feb 2020 15:07:37 -0600 Subject: [PATCH 20/25] Address review comments - Fix test crash - Move common functions to helpers - Add more schema validations - Add Update tests --- azurerm/helpers/azure/monitor.go | 116 ++++++++++++++ ...rce_monitor_scheduled_query_rules_alert.go | 14 +- ...ource_monitor_scheduled_query_rules_log.go | 17 +- ...arm_monitor_scheduled_query_rules_alert.go | 101 +++--------- ...e_arm_monitor_scheduled_query_rules_log.go | 75 ++------- ...onitor_scheduled_query_rules_alert_test.go | 127 ++------------- ..._monitor_scheduled_query_rules_log_test.go | 44 +---- ...onitor_scheduled_query_rules_alert_test.go | 150 +++++++++++++++++- ..._monitor_scheduled_query_rules_log_test.go | 131 ++++++++++++++- ..._scheduled_query_rules_alert.html.markdown | 3 +- ...or_scheduled_query_rules_log.html.markdown | 1 - ..._scheduled_query_rules_alert.html.markdown | 5 +- ...or_scheduled_query_rules_log.html.markdown | 4 +- 13 files changed, 450 insertions(+), 338 deletions(-) diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/helpers/azure/monitor.go index f5bf82a5bcf2..0560c1f02786 100644 --- a/azurerm/helpers/azure/monitor.go +++ b/azurerm/helpers/azure/monitor.go @@ -2,8 +2,124 @@ package azure import ( "fmt" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2019-06-01/insights" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) +func FlattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { + result := make([]interface{}, 0) + v := make(map[string]interface{}) + + if input != nil { + if input.ActionGroup != nil { + v["action_group"] = *input.ActionGroup + } + v["email_subject"] = input.EmailSubject + v["custom_webhook_payload"] = input.CustomWebhookPayload + } + result = append(result, v) + + return result +} + +func ExpandMonitorScheduledQueryRulesCommonSource(d *schema.ResourceData) *insights.Source { + authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() + dataSourceID := d.Get("data_source_id").(string) + query, ok := d.GetOk("query") + source := insights.Source{ + AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), + DataSourceID: utils.String(dataSourceID), + QueryType: insights.ResultCount, + } + if ok { + source.Query = utils.String(query.(string)) + } + + return &source +} + +func FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { + result := make(map[string]interface{}) + + if input == nil { + return []interface{}{} + } + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + result["metric_trigger_type"] = string(input.MetricTriggerType) + + if input.MetricColumn != nil { + result["metric_column"] = *input.MetricColumn + } + return []interface{}{result} +} + +func FlattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { + result := make(map[string]interface{}) + + result["operator"] = string(input.ThresholdOperator) + + if input.Threshold != nil { + result["threshold"] = *input.Threshold + } + + if input.MetricTrigger != nil { + result["metric_trigger"] = FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) + } + + return []interface{}{result} +} + +func FlattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, criteria := range *input { + v := make(map[string]interface{}) + + v["dimension"] = FlattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) + v["metric_name"] = *criteria.MetricName + + result = append(result, v) + } + } + + return result +} + +func FlattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { + result := make([]interface{}, 0) + + if input != nil { + for _, dimension := range *input { + v := make(map[string]interface{}) + + if dimension.Name != nil { + v["name"] = *dimension.Name + } + + if dimension.Operator != nil { + v["operator"] = *dimension.Operator + } + + if dimension.Values != nil { + v["values"] = *dimension.Values + } + + result = append(result, v) + } + } + + return result +} + // ValidateThreshold checks that a threshold value is between 0 and 10000 // and is a whole number. The azure-sdk-for-go expects this value to be a float64 // but the user validation rules want an integer. diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go index cc535fed1452..c7089ad132da 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -149,18 +149,20 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) + name := d.Get("name").(string) resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + return fmt.Errorf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q: %+v", name, resourceGroup, err) } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.SetId(*resp.ID) + + d.Set("name", name) d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) @@ -175,9 +177,9 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me action, ok := resp.Action.(insights.AlertingAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + if err = d.Set("action", azure.FlattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -186,7 +188,7 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", azure.FlattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index bad7e1f79797..ce22485f3879 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -85,10 +85,6 @@ func dataSourceArmMonitorScheduledQueryRulesLog() *schema.Resource { Type: schema.TypeBool, Computed: true, }, - "query_type": { - Type: schema.TypeString, - Computed: true, - }, "tags": tags.SchemaDataSource(), }, @@ -100,18 +96,20 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - name := d.Get("name").(string) resourceGroup := d.Get("resource_group_name").(string) + name := d.Get("name").(string) resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Error: Scheduled Query Rule %q was not found", name) + return fmt.Errorf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q: %+v", name, resourceGroup, err) } - return fmt.Errorf("Error reading Scheduled Query Rule: %+v", err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.SetId(*resp.ID) + + d.Set("name", name) d.Set("resource_group_name", resourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) @@ -126,9 +124,9 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta action, ok := resp.Action.(insights.LogToMetricAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + if err = d.Set("criteria", azure.FlattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { return fmt.Errorf("Error setting `criteria`: %+v", err) } @@ -148,7 +146,6 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta if source.DataSourceID != nil { d.Set("data_source_id", source.DataSourceID) } - d.Set("query_type", string(source.QueryType)) } return tags.FlattenAndSet(d, resp.Tags) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 6ea171c6cd89..25ede04fd169 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -58,8 +58,9 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { }, }, "action": { - Type: schema.TypeSet, - Optional: true, + Type: schema.TypeList, + Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "action_group": { @@ -133,13 +134,15 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { ValidateFunc: validation.IntBetween(5, 2880), }, "trigger": { - Type: schema.TypeSet, + Type: schema.TypeList, Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_trigger": { - Type: schema.TypeSet, + Type: schema.TypeList, Optional: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_column": { @@ -214,7 +217,9 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa query := d.Get("query").(string) _, ok := d.GetOk("metric_trigger") if ok { - if !(strings.Contains(query, "summarize") && strings.Contains(query, "AggregatedValue") && strings.Contains(query, "bin")) { + if !(strings.Contains(query, "summarize") && + strings.Contains(query, "AggregatedValue") && + strings.Contains(query, "bin")) { return fmt.Errorf("Error in parameter values for Scheduled Query Rules %q (Resource Group %q): query must contain summarize, AggregatedValue, and bin when metric_trigger is specified", name, resourceGroup) } } @@ -242,7 +247,7 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa location := azure.NormalizeLocation(d.Get("location")) - source := expandMonitorScheduledQueryRulesAlertSource(d) + source := azure.ExpandMonitorScheduledQueryRulesCommonSource(d) t := d.Get("tags").(map[string]interface{}) expandedTags := tags.Expand(t) @@ -260,7 +265,7 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa } if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error creating or updating Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } read, err := client.Get(ctx, resourceGroup, name) @@ -290,11 +295,11 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q", name, resourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.Set("name", name) @@ -303,19 +308,18 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta d.Set("location", azure.NormalizeLocation(*location)) } + d.Set("description", resp.Description) if resp.Enabled == insights.True { d.Set("enabled", true) } else { d.Set("enabled", false) } - d.Set("description", resp.Description) - action, ok := resp.Action.(insights.AlertingAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + if err = d.Set("action", azure.FlattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -324,7 +328,7 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", azure.FlattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } @@ -367,7 +371,7 @@ func resourceArmMonitorScheduledQueryRulesAlertDelete(d *schema.ResourceData, me if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error deleting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } } @@ -454,20 +458,6 @@ func expandMonitorScheduledQueryRulesAlertSchedule(d *schema.ResourceData) *insi return &schedule } -func expandMonitorScheduledQueryRulesAlertSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - query := d.Get("query").(string) - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - Query: utils.String(query), - QueryType: insights.ResultCount, - } - - return &source -} - func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights.TriggerCondition { result := insights.TriggerCondition{} if len(input) == 0 { @@ -491,56 +481,3 @@ func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights return &result } - -func flattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { - result := make([]interface{}, 0) - v := make(map[string]interface{}) - - if input != nil { - if input.ActionGroup != nil { - v["action_group"] = *input.ActionGroup - } - v["email_subject"] = input.EmailSubject - v["custom_webhook_payload"] = input.CustomWebhookPayload - } - result = append(result, v) - - return result -} - -func flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { - result := make(map[string]interface{}) - - if input == nil { - return []interface{}{} - } - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - result["metric_trigger_type"] = string(input.MetricTriggerType) - - if input.MetricColumn != nil { - result["metric_column"] = *input.MetricColumn - } - return []interface{}{result} -} - -func flattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { - result := make(map[string]interface{}) - - result["operator"] = string(input.ThresholdOperator) - - if input.Threshold != nil { - result["threshold"] = *input.Threshold - } - - if input.MetricTrigger != nil { - result["metric_trigger"] = flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) - } - - return []interface{}{result} -} diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index f9537f6a7306..1ff8e7ca63ae 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -57,8 +57,9 @@ func resourceArmMonitorScheduledQueryRulesLog() *schema.Resource { }, "criteria": { - Type: schema.TypeSet, + Type: schema.TypeList, Required: true, + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "dimension": { @@ -152,7 +153,7 @@ func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData location := azure.NormalizeLocation(d.Get("location")) - source := expandMonitorScheduledQueryRulesLogSource(d) + source := azure.ExpandMonitorScheduledQueryRulesCommonSource(d) t := d.Get("tags").(map[string]interface{}) expandedTags := tags.Expand(t) @@ -169,7 +170,7 @@ func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData } if _, err := client.CreateOrUpdate(ctx, resourceGroup, name, parameters); err != nil { - return fmt.Errorf("Error creating or updating scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error creating or updating Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } read, err := client.Get(ctx, resourceGroup, name) @@ -199,11 +200,11 @@ func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta i resp, err := client.Get(ctx, resourceGroup, name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q - removing from state!", name, resourceGroup) + log.Printf("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q", name, resourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error getting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error getting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } d.Set("name", name) @@ -212,19 +213,18 @@ func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta i d.Set("location", azure.NormalizeLocation(*location)) } + d.Set("description", resp.Description) if resp.Enabled == insights.True { d.Set("enabled", true) } else { d.Set("enabled", false) } - d.Set("description", resp.Description) - action, ok := resp.Action.(insights.LogToMetricAction) if !ok { - return fmt.Errorf("Wrong action type in scheduled query rule %q (resource group %q): %T", name, resourceGroup, resp.Action) + return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + if err = d.Set("criteria", azure.FlattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { return fmt.Errorf("Error setting `criteria`: %+v", err) } @@ -254,7 +254,7 @@ func resourceArmMonitorScheduledQueryRulesLogDelete(d *schema.ResourceData, meta if resp, err := client.Delete(ctx, resourceGroup, name); err != nil { if !response.WasNotFound(resp.Response) { - return fmt.Errorf("Error deleting scheduled query rule %q (resource group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("Error deleting Scheduled Query Rule %q (resource group %q): %+v", name, resourceGroup, err) } } @@ -311,58 +311,3 @@ func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) * return &action } - -func expandMonitorScheduledQueryRulesLogSource(d *schema.ResourceData) *insights.Source { - authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() - dataSourceID := d.Get("data_source_id").(string) - source := insights.Source{ - AuthorizedResources: utils.ExpandStringSlice(authorizedResourceIDs), - DataSourceID: utils.String(dataSourceID), - QueryType: insights.ResultCount, - } - - return &source -} - -func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, criteria := range *input { - v := make(map[string]interface{}) - - v["dimension"] = flattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) - v["metric_name"] = *criteria.MetricName - - result = append(result, v) - } - } - - return result -} - -func flattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { - result := make([]interface{}, 0) - - if input != nil { - for _, dimension := range *input { - v := make(map[string]interface{}) - - if dimension.Name != nil { - v["name"] = *dimension.Name - } - - if dimension.Operator != nil { - v["operator"] = *dimension.Operator - } - - if dimension.Values != nil { - v["values"] = *dimension.Values - } - - result = append(result, v) - } - } - - return result -} diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index 4f4193912807..e1955393eb10 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -9,7 +9,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingAction(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ @@ -26,7 +26,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingAction(t *testin }) } -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingActionCrossResource(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ @@ -45,133 +45,26 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResou func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) + template := testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-monitor-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - - frequency = 60 - time_window = 60 - - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} +%s data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + name = basename(azurerm_monitor_scheduled_query_rules_alert.test.id) resource_group_name = "${azurerm_resource_group.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +`, template) } func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { - ts := time.Now().Format(time.RFC3339) - + template := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-monitor-%d" - location = "%s" -} - -resource "azurerm_log_analytics_workspace" "test" { - name = "acctestWorkspace-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_log_analytics_workspace" "test2" { - name = "acctestWorkspace2-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - sku = "PerGB2018" - retention_in_days = 30 -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "acctestSqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test alerting action" - enabled = true - - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - data_source_id = "${azurerm_log_analytics_workspace.test.id}" - query_type = "ResultCount" - authorized_resource_ids = ["${azurerm_log_analytics_workspace.test.id}", "${azurerm_log_analytics_workspace.test2.id}"] - - frequency = 60 - time_window = 60 - - severity = 3 - action { - action_group = ["${azurerm_monitor_action_group.test.id}"] - email_subject = "Custom alert email subject" - } - - trigger { - operator = "GreaterThan" - threshold = 5000 - metric_trigger { - operator = "GreaterThan" - threshold = 1 - metric_trigger_type = "Total" - metric_column = "TimeGenerated" - } - } -} +%s data "azurerm_monitor_scheduled_query_rules_alert" "test" { - name = "${azurerm_monitor_scheduled_query_rules_alert.test.name}" + name = basename(azurerm_monitor_scheduled_query_rules_alert.test.id) resource_group_name = "${azurerm_resource_group.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +`, template) } diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index d25c6a7de355..4d17e1662fb1 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -8,7 +8,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRulesLogToMetricAction(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ @@ -26,47 +26,13 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricAction(t *tes } func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { + template := testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data) return fmt.Sprintf(` -resource "azurerm_resource_group" "test" { - name = "acctestRG-monitor-%d" - location = "%s" -} - -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" - location = "${azurerm_resource_group.test.location}" - resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" -} - -resource "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "acctestsqr-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - location = "${azurerm_resource_group.test.location}" - description = "test log to metric action" - enabled = true - - data_source_id = "${azurerm_application_insights.test.id}" - - criteria { - metric_name = "Average_%% Idle Time" - dimension { - name = "InstanceName" - operator = "Include" - values = ["50"] - } - } -} +%s data "azurerm_monitor_scheduled_query_rules_log" "test" { - name = "${azurerm_monitor_scheduled_query_rules_log.test.name}" + name = basename(azurerm_monitor_scheduled_query_rules_log.test.id) resource_group_name = "${azurerm_resource_group.test.name}" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, template) } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index a558a5359366..3ecf0a52bb0a 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -12,8 +12,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) -func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") + ts := time.Now().Format(time.RFC3339) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -21,7 +22,53 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_alertingAction(data), + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") + ts := time.Now().Format(time.RFC3339) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_update(data, ts), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_complete(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), @@ -40,7 +87,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data), + Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), ), @@ -50,7 +97,95 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }) } -func testAccAzureRMMonitorScheduledQueryRules_alertingAction(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data acceptance.TestData, ts string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + + frequency = 60 + time_window = 60 + + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + } + + trigger { + operator = "GreaterThan" + threshold = 5000 + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_update(data acceptance.TestData, ts string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_alert" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + data_source_id = "${azurerm_application_insights.test.id}" + query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + enabled = false + description = "test description" + + frequency = 30 + time_window = 30 + + action { + action_group = ["${azurerm_monitor_action_group.test.id}"] + } + + trigger { + operator = "GreaterThan" + threshold = 1000 + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) +} + +func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_complete(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -81,12 +216,12 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { data_source_id = "${azurerm_application_insights.test.id}" query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - query_type = "ResultCount" frequency = 60 time_window = 60 - severity = 3 + severity = 3 + throttling = 5 action { action_group = ["${azurerm_monitor_action_group.test.id}"] email_subject = "Custom alert email subject" @@ -107,7 +242,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResource(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -145,7 +280,6 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - query_type = "ResultCount" frequency = 60 time_window = 60 diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index 0706ca581078..fb742cd513ee 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -11,7 +11,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) -func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_basic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ @@ -20,7 +20,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data), + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), ), @@ -30,7 +30,132 @@ func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { }) } -func testAccAzureRMMonitorScheduledQueryRules_logToMetricAction(data acceptance.TestData) string { +func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_complete(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "InstanceName" + operator = "Include" + values = ["50"] + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-monitor-%d" + location = "%s" +} + +resource "azurerm_application_insights" "test" { + name = "acctestAppInsights-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + application_type = "web" +} + +resource "azurerm_monitor_action_group" "test" { + name = "acctestActionGroup-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "acctestag" +} + +resource "azurerm_monitor_scheduled_query_rules_log" "test" { + name = "acctestsqr-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + description = "test log to metric action" + enabled = true + + data_source_id = "${azurerm_application_insights.test.id}" + + criteria { + metric_name = "Average_%% Idle Time" + dimension { + name = "Computer" + operator = "Include" + values = ["25"] + } + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index 7e513bf3c885..a48871a910b7 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -35,10 +35,9 @@ output "query_rule_id" { * `authorized_resource_ids` - List of Resource IDs referred into query. * `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. -* `enabled` - Whether this scheduled query rule is enabled. +* `enabled` - Whether this Scheduled Query Rule is enabled. * `frequency` - Frequency at which rule condition should be evaluated. * `query` - Log search query. -* `query_type` - Must equal "ResultCount". * `time_window` - Time window for which data needs to be fetched for query. * `severity` - Severity of the alert. * `throttling` - Time for which alerts should be throttled or suppressed. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index af8890e478d2..47cb9bdbdd23 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -35,7 +35,6 @@ output "query_rule_id" { * `data_source_id` - The resource URI over which log search query is to be run. * `description` - The description of the Scheduled Query Rule. * `enabled` - Whether this Scheduled Query Rule is enabled. -* `throttling` - Time for which alerts should be throttled or suppressed. --- diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 09cc58779091..d00a1f636a4f 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -127,12 +127,13 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. * `data_source_id` - (Required) The resource URI over which log search query is to be run. * `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. Values must be between 5 and 1440 (inclusive). +* `query` - (Required) Log search query. * `time_window` - (Required) Time window for which data needs to be fetched for query (must be greater than or equal to `frequency`). Values must be between 5 and 2880 (inclusive). * `trigger` - (Required) The condition that results in the alert rule being run. +* `action` - (Required) An `action` block as defined below. * `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. -* `action` - (Optional) An `action` block as defined below. * `description` - (Optional) The description of the Scheduled Query Rule. -* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. +* `enabled` - (Optional) Whether this Scheduled Query Rule is enabled. Default is `true`. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. * `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 (inclusive). diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 48beb3b33359..d804aa2180d2 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -53,9 +53,7 @@ The following arguments are supported: * `criteria` - (Required) A `criteria` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. * `description` - (Optional) The description of the Scheduled Query Rule. -* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. -* `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 ( -inclusive). +* `enabled` - (Optional) Whether this Scheduled Query Rule is enabled. Default is `true`. --- From db64f0d3d39d3d39d5eaeb4c8d129ad7492582e7 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 22 Feb 2020 11:25:47 -0600 Subject: [PATCH 21/25] Fix type assertions; simplify cross-resource query example --- ...arm_monitor_scheduled_query_rules_alert.go | 6 ++--- ..._scheduled_query_rules_alert.html.markdown | 27 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 25ede04fd169..161439a24aca 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -379,13 +379,13 @@ func resourceArmMonitorScheduledQueryRulesAlertDelete(d *schema.ResourceData, me } func expandMonitorScheduledQueryRulesAlertingAction(d *schema.ResourceData) *insights.AlertingAction { - alertActionRaw := d.Get("action").(*schema.Set).List() + alertActionRaw := d.Get("action").([]interface{}) alertAction := expandMonitorScheduledQueryRulesAlertAction(alertActionRaw) severityRaw := d.Get("severity").(int) severity := strconv.Itoa(severityRaw) throttling := d.Get("throttling").(int) - triggerRaw := d.Get("trigger").(*schema.Set).List() + triggerRaw := d.Get("trigger").([]interface{}) trigger := expandMonitorScheduledQueryRulesAlertTrigger(triggerRaw) action := insights.AlertingAction{ @@ -472,7 +472,7 @@ func expandMonitorScheduledQueryRulesAlertTrigger(input []interface{}) *insights if !ok { continue } - metricTriggerRaw := v["metric_trigger"].(*schema.Set).List() + metricTriggerRaw := v["metric_trigger"].([]interface{}) result.ThresholdOperator = insights.ConditionalOperator(v["operator"].(string)) result.Threshold = utils.Float(v["threshold"].(float64)) diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index d00a1f636a4f..63b0d5418859 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -25,19 +25,17 @@ resource "azurerm_application_insights" "example" { application_type = "web" } -resource "azurerm_log_analytics_workspace" "example" { - name = "loganalytics" - location = azurerm_resource_group.example.location +resource "azurerm_application_insights" "example2" { + name = "appinsights2" + location = var.location resource_group_name = azurerm_resource_group.example.name - sku = "PerGB2018" - retention_in_days = 30 + application_type = "web" } - # Example: Alerting Action with result count trigger # Alert if more than three HTTP requests returned a >= 500 result code # in the past 30 minutes -resource "azurerm_scheduled_query_rule_alert" "example" { +resource "azurerm_monitor_scheduled_query_rules_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name @@ -63,7 +61,7 @@ resource "azurerm_scheduled_query_rule_alert" "example" { # Example: Alerting Action with metric trigger # Alert if more than three HTTP requests returned a >= 500 result code # in the past 30 minutes that have the same operation (ie: GET /) -resource "azurerm_scheduled_query_rule_alert" "example" { +resource "azurerm_monitor_scheduled_query_rules_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name @@ -93,13 +91,16 @@ resource "azurerm_scheduled_query_rule_alert" "example" { } # Example: Alerting Action Cross-Resource -resource "azurerm_scheduled_query_rule_alert" "example2" { +# Enables use of cross-resource queries to analyze query results across +# multiple Application Insights or Log Analytics resources. +# Alert if more than three HTTP requests returned a >= 500 result code +# in either of the Insights resources in the past 30 minutes. +resource "azurerm_monitor_scheduled_query_rules_alert" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - authorized_resource_ids = [azurerm_application_insights.example.id, - azurerm_log_analytics_workspace.example.id] + authorized_resource_ids = [azurerm_application_insights.example2.id] action { action_group = [] email_subject = "Email Header" @@ -109,8 +110,8 @@ resource "azurerm_scheduled_query_rule_alert" "example2" { description = "Scheduled query rule Alerting Action cross-resource example" enabled = true frequency = 5 - query = format("let a=workspace('%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) - severity = "1" + query = format("let a=requests | where toint(resultCode) >= 500 | extend fail=1; let b=app('%s').requests | where toint(resultCode) >= 500 | extend fail=1; a | join b on fail", azurerm_application_insights.example2.id) + severity = 1 time_window = 30 trigger { operator = "GreaterThan" From 37b2c396cccbe6271262b6ba363f7518a092cf8c Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Sat, 22 Feb 2020 12:27:01 -0600 Subject: [PATCH 22/25] Review updates - Add metric alerts to LogToMetric tests and docs - Fix type assert from change to TypeList - Fix a couple typos --- ...e_arm_monitor_scheduled_query_rules_log.go | 2 +- ...onitor_scheduled_query_rules_alert_test.go | 4 +- ..._monitor_scheduled_query_rules_log_test.go | 74 +++++++++++-------- ...or_scheduled_query_rules_log.html.markdown | 54 +++++++++++--- 4 files changed, 90 insertions(+), 44 deletions(-) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index 1ff8e7ca63ae..3027f48b8551 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -301,7 +301,7 @@ func expandMonitorScheduledQueryRulesLogCriteria(input []interface{}) *[]insight } func expandMonitorScheduledQueryRulesLogToMetricAction(d *schema.ResourceData) *insights.LogToMetricAction { - criteriaRaw := d.Get("criteria").(*schema.Set).List() + criteriaRaw := d.Get("criteria").([]interface{}) criteria := expandMonitorScheduledQueryRulesLogCriteria(criteriaRaw) action := insights.LogToMetricAction{ diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index 3ecf0a52bb0a..274c4f0d9636 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -258,8 +258,8 @@ resource "azurerm_application_insights" "test" { resource "azurerm_log_analytics_workspace" "test" { name = "acctestWorkspace-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" sku = "PerGB2018" retention_in_days = 30 } diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index fb742cd513ee..d1ea512b1dd3 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -82,17 +82,12 @@ resource "azurerm_resource_group" "test" { location = "%s" } -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" + sku = "PerGB2018" + retention_in_days = 30 } resource "azurerm_monitor_scheduled_query_rules_log" "test" { @@ -100,18 +95,18 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" criteria { metric_name = "Average_%% Idle Time" dimension { name = "InstanceName" operator = "Include" - values = ["50"] + values = ["1"] } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data acceptance.TestData) string { @@ -121,17 +116,12 @@ resource "azurerm_resource_group" "test" { location = "%s" } -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" -} - -resource "azurerm_monitor_action_group" "test" { - name = "acctestActionGroup-%d" - resource_group_name = "${azurerm_resource_group.test.name}" - short_name = "acctestag" + sku = "PerGB2018" + retention_in_days = 30 } resource "azurerm_monitor_scheduled_query_rules_log" "test" { @@ -141,18 +131,18 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { description = "test log to metric action" enabled = true - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" criteria { metric_name = "Average_%% Idle Time" dimension { - name = "Computer" + name = "InstanceName" operator = "Include" - values = ["25"] + values = ["2"] } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data acceptance.TestData) string { @@ -162,11 +152,12 @@ resource "azurerm_resource_group" "test" { location = "%s" } -resource "azurerm_application_insights" "test" { - name = "acctestAppInsights-%d" +resource "azurerm_log_analytics_workspace" "test" { + name = "acctestWorkspace-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - application_type = "web" + sku = "PerGB2018" + retention_in_days = 30 } resource "azurerm_monitor_action_group" "test" { @@ -182,18 +173,37 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { description = "test log to metric action" enabled = true - data_source_id = "${azurerm_application_insights.test.id}" + data_source_id = "${azurerm_log_analytics_workspace.test.id}" criteria { metric_name = "Average_%% Idle Time" dimension { - name = "InstanceName" + name = "Computer" operator = "Include" - values = ["50"] + values = ["*"] } } } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) + +resource "azurerm_monitor_metric_alert" "test" { + name = "acctestmal-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + scopes = ["${azurerm_log_analytics_workspace.test.id}"] + description = "Action will be triggered when Average %% Idle Time is less than 10." + + criteria { + metric_namespace = "Microsoft.OperationalInsights/workspaces" + metric_name = "${azurerm_monitor_scheduled_query_rules_log.test.criteria[0].metric_name}" + aggregation = "Average" + operator = "LessThan" + threshold = 10 + } + + action { + action_group_id = "${azurerm_monitor_action_group.test.id}" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) error { diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index d804aa2180d2..20d2db6663e9 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -18,30 +18,66 @@ resource "azurerm_resource_group" "example" { location = "West US" } -resource "azurerm_application_insights" "example" { - name = "appinsights" - location = var.location +resource "azurerm_log_analytics_workspace" "example" { + name = "loganalytics" + location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name - application_type = "web" + sku = "PerGB2018" + retention_in_days = 30 } -resource "azurerm_scheduled_query_rule_log" "example3" { - name = format("%s-queryrule3", var.prefix) +# Create Azure Monitor metric from log analytics data for +# the Computer named 'targetVM'. +resource "azurerm_scheduled_query_rule_log" "example" { + name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location resource_group_name = azurerm_resource_group.example.name criteria { metric_name = "Average_% Idle Time" dimensions { - name = "InstanceName" + name = "Computer" operator = "Include" - values = [""] + values = ["targetVM"] } } - data_source_id = azurerm_application_insights.example.id + data_source_id = azurerm_log_analytics_workspace.example.id description = "Scheduled query rule LogToMetric example" enabled = true } + +resource "azurerm_monitor_action_group" "example" { + name = "example-actiongroup" + resource_group_name = azurerm_resource_group.example.name + short_name = "exampleact" + + webhook_receiver { + name = "callmyapi" + service_uri = "http://example.com/alert" + } +} + +# Create an alert on the new Scheduled Query Rules metric +resource "azurerm_monitor_metric_alert" "example" { + name = "example-metricalert" + resource_group_name = azurerm_resource_group.example.name + scopes = [azurerm_log_analytics_workspace.example.id] + description = "Action will be triggered when Average_% Idle Time metric is less than 10." + frequency = "PT1M" + window_size = "PT5M" + + criteria { + metric_namespace = "Microsoft.OperationalInsights/workspaces" + metric_name = azurerm_scheduled_query_rules_log.example.criteria[0].metric_name + aggregation = "Average" + operator = "LessThan" + threshold = 10 + } + + action { + action_group_id = azurerm_monitor_action_group.example.id + } +} ``` ## Argument Reference From 347753ae1a95e52208d69dee813976a0dd310ad5 Mon Sep 17 00:00:00 2001 From: David McPike Date: Sat, 22 Feb 2020 15:33:43 -0600 Subject: [PATCH 23/25] Add MaxItems for cross-resource query --- .../monitor/resource_arm_monitor_scheduled_query_rules_alert.go | 1 + 1 file changed, 1 insertion(+) diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 161439a24aca..4b8b335fafd1 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -52,6 +52,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { "authorized_resource_ids": { Type: schema.TypeSet, Optional: true, + MaxItems: 100, Elem: &schema.Schema{ Type: schema.TypeString, ValidateFunc: azure.ValidateResourceID, From 27ad7aece3dfb873d05e0dd9665ff61ab9c4cec4 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 3 Mar 2020 15:15:55 -0600 Subject: [PATCH 24/25] Address review comments - Improve docs - Use heredoc strings in docs and test queries - Move shared functions into monitor package - Add underscores to test function names --- .../services/monitor/common_monitor.go} | 25 +++---- ...rce_monitor_scheduled_query_rules_alert.go | 4 +- ...ource_monitor_scheduled_query_rules_log.go | 2 +- ...arm_monitor_scheduled_query_rules_alert.go | 10 +-- ...e_arm_monitor_scheduled_query_rules_log.go | 4 +- ...onitor_scheduled_query_rules_alert_test.go | 16 ++-- ..._monitor_scheduled_query_rules_log_test.go | 8 +- ...onitor_scheduled_query_rules_alert_test.go | 75 ++++++++++++------- ..._monitor_scheduled_query_rules_log_test.go | 38 +++++----- ..._scheduled_query_rules_alert.html.markdown | 14 ++-- ...or_scheduled_query_rules_log.html.markdown | 14 ++-- ..._scheduled_query_rules_alert.html.markdown | 58 ++++++++------ ...or_scheduled_query_rules_log.html.markdown | 19 +++-- 13 files changed, 156 insertions(+), 131 deletions(-) rename azurerm/{helpers/azure/monitor.go => internal/services/monitor/common_monitor.go} (82%) diff --git a/azurerm/helpers/azure/monitor.go b/azurerm/internal/services/monitor/common_monitor.go similarity index 82% rename from azurerm/helpers/azure/monitor.go rename to azurerm/internal/services/monitor/common_monitor.go index 0560c1f02786..0754ff8aa411 100644 --- a/azurerm/helpers/azure/monitor.go +++ b/azurerm/internal/services/monitor/common_monitor.go @@ -1,4 +1,4 @@ -package azure +package monitor import ( "fmt" @@ -8,8 +8,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func FlattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { - result := make([]interface{}, 0) +func flattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGroup) []interface{} { v := make(map[string]interface{}) if input != nil { @@ -19,12 +18,10 @@ func FlattenAzureRmScheduledQueryRulesAlertAction(input *insights.AzNsActionGrou v["email_subject"] = input.EmailSubject v["custom_webhook_payload"] = input.CustomWebhookPayload } - result = append(result, v) - - return result + return []interface{}{v} } -func ExpandMonitorScheduledQueryRulesCommonSource(d *schema.ResourceData) *insights.Source { +func expandMonitorScheduledQueryRulesCommonSource(d *schema.ResourceData) *insights.Source { authorizedResourceIDs := d.Get("authorized_resource_ids").(*schema.Set).List() dataSourceID := d.Get("data_source_id").(string) query, ok := d.GetOk("query") @@ -40,7 +37,7 @@ func ExpandMonitorScheduledQueryRulesCommonSource(d *schema.ResourceData) *insig return &source } -func FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { +func flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetricTrigger) []interface{} { result := make(map[string]interface{}) if input == nil { @@ -61,7 +58,7 @@ func FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input *insights.LogMetr return []interface{}{result} } -func FlattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { +func flattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondition) []interface{} { result := make(map[string]interface{}) result["operator"] = string(input.ThresholdOperator) @@ -71,20 +68,20 @@ func FlattenAzureRmScheduledQueryRulesAlertTrigger(input *insights.TriggerCondit } if input.MetricTrigger != nil { - result["metric_trigger"] = FlattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) + result["metric_trigger"] = flattenAzureRmScheduledQueryRulesAlertMetricTrigger(input.MetricTrigger) } return []interface{}{result} } -func FlattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { +func flattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) []interface{} { result := make([]interface{}, 0) if input != nil { for _, criteria := range *input { v := make(map[string]interface{}) - v["dimension"] = FlattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) + v["dimension"] = flattenAzureRmScheduledQueryRulesLogDimension(criteria.Dimensions) v["metric_name"] = *criteria.MetricName result = append(result, v) @@ -94,7 +91,7 @@ func FlattenAzureRmScheduledQueryRulesLogCriteria(input *[]insights.Criteria) [] return result } -func FlattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { +func flattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) []interface{} { result := make([]interface{}, 0) if input != nil { @@ -123,7 +120,7 @@ func FlattenAzureRmScheduledQueryRulesLogDimension(input *[]insights.Dimension) // ValidateThreshold checks that a threshold value is between 0 and 10000 // and is a whole number. The azure-sdk-for-go expects this value to be a float64 // but the user validation rules want an integer. -func ValidateMonitorScheduledQueryRulesAlertThreshold(i interface{}, k string) (warnings []string, errors []error) { +func validateMonitorScheduledQueryRulesAlertThreshold(i interface{}, k string) (warnings []string, errors []error) { v, ok := i.(float64) if !ok { errors = append(errors, fmt.Errorf("expected type of %q to be float64", k)) diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go index c7089ad132da..44e6634a01d9 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go @@ -179,7 +179,7 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me if !ok { return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("action", azure.FlattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -188,7 +188,7 @@ func dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, me } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", azure.FlattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } diff --git a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go index ce22485f3879..3710667bcf8d 100644 --- a/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_log.go @@ -126,7 +126,7 @@ func dataSourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta if !ok { return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("criteria", azure.FlattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { return fmt.Errorf("Error setting `criteria`: %+v", err) } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go index 4b8b335fafd1..e8ad5526e7c4 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_alert.go @@ -171,7 +171,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { "threshold": { Type: schema.TypeFloat, Required: true, - ValidateFunc: azure.ValidateMonitorScheduledQueryRulesAlertThreshold, + ValidateFunc: validateMonitorScheduledQueryRulesAlertThreshold, }, }, }, @@ -188,7 +188,7 @@ func resourceArmMonitorScheduledQueryRulesAlert() *schema.Resource { "threshold": { Type: schema.TypeFloat, Required: true, - ValidateFunc: azure.ValidateMonitorScheduledQueryRulesAlertThreshold, + ValidateFunc: validateMonitorScheduledQueryRulesAlertThreshold, }, }, }, @@ -248,7 +248,7 @@ func resourceArmMonitorScheduledQueryRulesAlertCreateUpdate(d *schema.ResourceDa location := azure.NormalizeLocation(d.Get("location")) - source := azure.ExpandMonitorScheduledQueryRulesCommonSource(d) + source := expandMonitorScheduledQueryRulesCommonSource(d) t := d.Get("tags").(map[string]interface{}) expandedTags := tags.Expand(t) @@ -320,7 +320,7 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta if !ok { return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("action", azure.FlattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { + if err = d.Set("action", flattenAzureRmScheduledQueryRulesAlertAction(action.AznsAction)); err != nil { return fmt.Errorf("Error setting `action`: %+v", err) } severity, err := strconv.Atoi(string(action.Severity)) @@ -329,7 +329,7 @@ func resourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta } d.Set("severity", severity) d.Set("throttling", action.ThrottlingInMin) - if err = d.Set("trigger", azure.FlattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { + if err = d.Set("trigger", flattenAzureRmScheduledQueryRulesAlertTrigger(action.Trigger)); err != nil { return fmt.Errorf("Error setting `trigger`: %+v", err) } diff --git a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go index 3027f48b8551..4efacb839a5a 100644 --- a/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go +++ b/azurerm/internal/services/monitor/resource_arm_monitor_scheduled_query_rules_log.go @@ -153,7 +153,7 @@ func resourceArmMonitorScheduledQueryRulesLogCreateUpdate(d *schema.ResourceData location := azure.NormalizeLocation(d.Get("location")) - source := azure.ExpandMonitorScheduledQueryRulesCommonSource(d) + source := expandMonitorScheduledQueryRulesCommonSource(d) t := d.Get("tags").(map[string]interface{}) expandedTags := tags.Expand(t) @@ -224,7 +224,7 @@ func resourceArmMonitorScheduledQueryRulesLogRead(d *schema.ResourceData, meta i if !ok { return fmt.Errorf("Wrong action type in Scheduled Query Rule %q (resource group %q): %T", name, resourceGroup, resp.Action) } - if err = d.Set("criteria", azure.FlattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { + if err = d.Set("criteria", flattenAzureRmScheduledQueryRulesLogCriteria(action.Criteria)); err != nil { return fmt.Errorf("Error setting `criteria`: %+v", err) } diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go index e1955393eb10..382002fc4d03 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_alert_test.go @@ -9,7 +9,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingAction(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_AlertingAction(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ @@ -17,7 +17,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingAction(t *testing Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data), + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_AlertingActionConfig(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), @@ -26,7 +26,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingAction(t *testing }) } -func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingActionCrossResource(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ @@ -34,7 +34,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingActionCrossResour Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_AlertingActionCrossResourceConfig(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), @@ -43,9 +43,9 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRulesAlertingActionCrossResour }) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionConfig(data acceptance.TestData) string { +func testAccDataSourceAzureRMMonitorScheduledQueryRules_AlertingActionConfig(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) - template := testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts) + template := testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigBasic(data, ts) return fmt.Sprintf(` %s @@ -57,8 +57,8 @@ data "azurerm_monitor_scheduled_query_rules_alert" "test" { `, template) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { - template := testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data) +func testAccDataSourceAzureRMMonitorScheduledQueryRules_AlertingActionCrossResourceConfig(data acceptance.TestData) string { + template := testAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResourceConfig(data) return fmt.Sprintf(` %s diff --git a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go index 4d17e1662fb1..6c23137eb96f 100644 --- a/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/data_source_monitor_scheduled_query_rules_log_test.go @@ -8,7 +8,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" ) -func TestAccDataSourceAzureRMMonitorScheduledQueryRulesLogToMetricAction(t *testing.T) { +func TestAccDataSourceAzureRMMonitorScheduledQueryRules_LogToMetricAction(t *testing.T) { data := acceptance.BuildTestData(t, "data.azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ @@ -16,7 +16,7 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRulesLogToMetricAction(t *test Providers: acceptance.SupportedProviders, Steps: []resource.TestStep{ { - Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data), + Config: testAccDataSourceAzureRMMonitorScheduledQueryRules_LogToMetricActionConfig(data), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(data.ResourceName, "id"), ), @@ -25,8 +25,8 @@ func TestAccDataSourceAzureRMMonitorScheduledQueryRulesLogToMetricAction(t *test }) } -func testAccDataSourceAzureRMMonitorScheduledQueryRules_logToMetricActionConfig(data acceptance.TestData) string { - template := testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data) +func testAccDataSourceAzureRMMonitorScheduledQueryRules_LogToMetricActionConfig(data acceptance.TestData) string { + template := testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigBasic(data) return fmt.Sprintf(` %s diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go index 274c4f0d9636..65106b7ad9b7 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_alert_test.go @@ -12,19 +12,19 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) -func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_basic(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionBasic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") ts := time.Now().Format(time.RFC3339) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_AlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts), + Config: testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigBasic(data, ts), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_AlertExists(data.ResourceName), ), }, data.ImportStep(), @@ -32,26 +32,26 @@ func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_basic(t *testing.T) }) } -func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_update(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionUpdate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") ts := time.Now().Format(time.RFC3339) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_AlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data, ts), + Config: testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigBasic(data, ts), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_AlertExists(data.ResourceName), ), }, data.ImportStep(), { - Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_update(data, ts), + Config: testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigUpdate(data, ts), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_AlertExists(data.ResourceName), ), }, data.ImportStep(), @@ -59,18 +59,18 @@ func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_update(t *testing.T) }) } -func TestAccAzureRMMonitorScheduledQueryRulesAlertingAction_complete(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionComplete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_alert", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_AlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_complete(data), + Config: testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigComplete(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_AlertExists(data.ResourceName), ), }, data.ImportStep(), @@ -84,12 +84,12 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_AlertDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data), + Config: testAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResourceConfig(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesAlertExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_AlertExists(data.ResourceName), ), }, data.ImportStep(), @@ -97,7 +97,7 @@ func TestAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResource(t *tes }) } -func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_basic(data acceptance.TestData, ts string) string { +func testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigBasic(data acceptance.TestData, ts string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -123,7 +123,10 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { location = "${azurerm_resource_group.test.location}" data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" + query = <<-QUERY + let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; + d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h) + QUERY frequency = 60 time_window = 60 @@ -140,7 +143,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_update(data acceptance.TestData, ts string) string { +func testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigUpdate(data acceptance.TestData, ts string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -166,9 +169,13 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { location = "${azurerm_resource_group.test.location}" data_source_id = "${azurerm_application_insights.test.id}" - query = "let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h)" - enabled = false - description = "test description" + query = <<-QUERY + let d=datatable(TimeGenerated: datetime, usage_percent: double) [ '%s', 25.4, '%s', 75.4 ]; + d | summarize AggregatedValue=avg(usage_percent) by bin(TimeGenerated, 1h) + QUERY + + enabled = false + description = "test description" frequency = 30 time_window = 30 @@ -185,7 +192,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRulesAlertingActionConfig_complete(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_AlertingActionConfigComplete(data acceptance.TestData) string { ts := time.Now().Format(time.RFC3339) return fmt.Sprintf(` @@ -242,7 +249,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, ts, ts) } -func testAccAzureRMMonitorScheduledQueryRules_alertingActionCrossResourceConfig(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_AlertingActionCrossResourceConfig(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -279,7 +286,19 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { authorized_resource_ids = ["${azurerm_application_insights.test.id}", "${azurerm_log_analytics_workspace.test.id}"] data_source_id = "${azurerm_application_insights.test.id}" - query = format("let a=workspace('%%s').Perf | where Computer='dependency' and TimeGenerated > ago(1h) | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) | extend ts=tostring(TimeGenerated); let b=requests | where resultCode == '200' and timestamp > ago(1h) | summarize reqs=count() by bin(timestamp, 1m) | extend ts = tostring(timestamp); a | join b on $left.ts == $right.ts | where cpu > 50 and reqs > 5", azurerm_log_analytics_workspace.test.id) + query = format(<<-QUERY + let a=workspace('%%s').Perf + | where Computer='dependency' and TimeGenerated > ago(1h) + | where ObjectName == 'Processor' and CounterName == '%%%% Processor Time' + | summarize cpu=avg(CounterValue) by bin(TimeGenerated, 1m) + | extend ts=tostring(TimeGenerated); let b=requests + | where resultCode == '200' and timestamp > ago(1h) + | summarize reqs=count() by bin(timestamp, 1m) + | extend ts = tostring(timestamp); a + | join b on $left.ts == $right.ts + | where cpu > 50 and reqs > 5 +QUERY + , azurerm_log_analytics_workspace.test.id) frequency = 60 time_window = 60 @@ -298,7 +317,7 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy(s *terraform.State) error { +func testCheckAzureRMMonitorScheduledQueryRules_AlertDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -324,7 +343,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesAlertDestroy(s *terraform.State) return nil } -func testCheckAzureRMMonitorScheduledQueryRulesAlertExists(resourceName string) resource.TestCheckFunc { +func testCheckAzureRMMonitorScheduledQueryRules_AlertExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[resourceName] diff --git a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go index d1ea512b1dd3..c62f37193cd3 100644 --- a/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go +++ b/azurerm/internal/services/monitor/tests/resource_arm_monitor_scheduled_query_rules_log_test.go @@ -11,18 +11,18 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" ) -func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_basic(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricActionBasic(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_LogDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data), + Config: testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigBasic(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_LogExists(data.ResourceName), ), }, data.ImportStep(), @@ -30,25 +30,25 @@ func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_basic(t *testing. }) } -func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_update(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricActionUpdate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_LogDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data), + Config: testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigBasic(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_LogExists(data.ResourceName), ), }, data.ImportStep(), { - Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data), + Config: testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigUpdate(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_LogExists(data.ResourceName), ), }, data.ImportStep(), @@ -56,18 +56,18 @@ func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_update(t *testing }) } -func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_complete(t *testing.T) { +func TestAccAzureRMMonitorScheduledQueryRules_LogToMetricActionComplete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_monitor_scheduled_query_rules_log", "test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, Providers: acceptance.SupportedProviders, - CheckDestroy: testCheckAzureRMMonitorScheduledQueryRulesLogDestroy, + CheckDestroy: testCheckAzureRMMonitorScheduledQueryRules_LogDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data), + Config: testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigComplete(data), Check: resource.ComposeTestCheckFunc( - testCheckAzureRMMonitorScheduledQueryRulesLogExists(data.ResourceName), + testCheckAzureRMMonitorScheduledQueryRules_LogExists(data.ResourceName), ), }, data.ImportStep(), @@ -75,7 +75,7 @@ func TestAccAzureRMMonitorScheduledQueryRulesLogToMetricAction_complete(t *testi }) } -func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_basic(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigBasic(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -109,7 +109,7 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_update(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigUpdate(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -145,7 +145,7 @@ resource "azurerm_monitor_scheduled_query_rules_log" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) } -func testAccAzureRMMonitorScheduledQueryRulesLogToMetricActionConfig_complete(data acceptance.TestData) string { +func testAccAzureRMMonitorScheduledQueryRules_LogToMetricActionConfigComplete(data acceptance.TestData) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-monitor-%d" @@ -206,7 +206,7 @@ resource "azurerm_monitor_metric_alert" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger) } -func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) error { +func testCheckAzureRMMonitorScheduledQueryRules_LogDestroy(s *terraform.State) error { client := acceptance.AzureProvider.Meta().(*clients.Client).Monitor.ScheduledQueryRulesClient ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext @@ -232,7 +232,7 @@ func testCheckAzureRMMonitorScheduledQueryRulesLogDestroy(s *terraform.State) er return nil } -func testCheckAzureRMMonitorScheduledQueryRulesLogExists(resourceName string) resource.TestCheckFunc { +func testCheckAzureRMMonitorScheduledQueryRules_LogExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[resourceName] diff --git a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown index a48871a910b7..abe74d1c19d9 100644 --- a/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_alert.html.markdown @@ -3,12 +3,12 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" description: |- - Get information about the specified AlertingAction Scheduled Query Rule. + Get information about the specified AlertingAction Scheduled Query Rules resource. --- # Data Source: azurerm_monitor_scheduled_query_rules_alert -Use this data source to access the properties of an AlertingAction Scheduled Query Rule. +Use this data source to access the properties of an AlertingAction scheduled query rule. ## Example Usage @@ -25,17 +25,17 @@ output "query_rule_id" { ## Argument Reference -* `name` - (Required) Specifies the name of the Scheduled Query Rule. -* `resource_group_name` - (Required) Specifies the name of the resource group where the Scheduled Query Rule is located. +* `name` - (Required) Specifies the name of the scheduled query rule. +* `resource_group_name` - (Required) Specifies the name of the resource group where the scheduled query rule is located. ## Attributes Reference -* `id` - The ID of the Scheduled Query Rule. +* `id` - The ID of the scheduled query rule. * `action` - An `action` block as defined below. * `authorized_resource_ids` - List of Resource IDs referred into query. * `data_source_id` - The resource URI over which log search query is to be run. -* `description` - The description of the Scheduled Query Rule. -* `enabled` - Whether this Scheduled Query Rule is enabled. +* `description` - The description of the scheduled query rule. +* `enabled` - Whether this scheduled query rule is enabled. * `frequency` - Frequency at which rule condition should be evaluated. * `query` - Log search query. * `time_window` - Time window for which data needs to be fetched for query. diff --git a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown index 47cb9bdbdd23..9f994b7bcfe4 100644 --- a/website/docs/d/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/d/monitor_scheduled_query_rules_log.html.markdown @@ -3,12 +3,12 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" description: |- - Get information about the specified LogToMetricAction Scheduled Query Rule. + Get information about the specified LogToMetricAction Scheduled Query Rules resource. --- # Data Source: azurerm_monitor_scheduled_query_rules_log -Use this data source to access the properties of a LogToMetricAction Scheduled Query Rule. +Use this data source to access the properties of a LogToMetricAction scheduled query rule. ## Example Usage @@ -25,16 +25,16 @@ output "query_rule_id" { ## Argument Reference -* `name` - (Required) Specifies the name of the Scheduled Query Rule. -* `resource_group_name` - (Required) Specifies the name of the resource group where the Scheduled Query Rule is located. +* `name` - (Required) Specifies the name of the scheduled query rule. +* `resource_group_name` - (Required) Specifies the name of the resource group where the scheduled query rule is located. ## Attributes Reference -* `id` - The ID of the Scheduled Query Rule. +* `id` - The ID of the scheduled query rule. * `criteria` - A `criteria` block as defined below. * `data_source_id` - The resource URI over which log search query is to be run. -* `description` - The description of the Scheduled Query Rule. -* `enabled` - Whether this Scheduled Query Rule is enabled. +* `description` - The description of the scheduled query rule. +* `enabled` - Whether this scheduled query rule is enabled. --- diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index 63b0d5418859..fc8b98559eb5 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -3,12 +3,12 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_alert" description: |- - Manages an AlertingAction Scheduled Query Rule within Azure Monitor + Manages an AlertingAction Scheduled Query Rules resource within Azure Monitor --- # azurerm_monitor_scheduled_query_rules_alert -Manages an AlertingAction Scheduled Query Rule within Azure Monitor. +Manages an AlertingAction Scheduled Query Rules resource within Azure Monitor. ## Example Usage @@ -33,8 +33,6 @@ resource "azurerm_application_insights" "example2" { } # Example: Alerting Action with result count trigger -# Alert if more than three HTTP requests returned a >= 500 result code -# in the past 30 minutes resource "azurerm_monitor_scheduled_query_rules_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location @@ -46,11 +44,16 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example" { custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Result count trigger example - alert when total results cross threshold" + description = "Alert when total results cross threshold" enabled = true - frequency = 5 - query = "requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by bin(timestamp, 5m)" + # Count all requests with server error result code grouped into 5-minute bins + query = <<-QUERY + requests + | where tolong(resultCode) >= 500 + | summarize count() by bin(timestamp, 5m) + QUERY severity = 1 + frequency = 5 time_window = 30 trigger { operator = "GreaterThan" @@ -59,8 +62,6 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example" { } # Example: Alerting Action with metric trigger -# Alert if more than three HTTP requests returned a >= 500 result code -# in the past 30 minutes that have the same operation (ie: GET /) resource "azurerm_monitor_scheduled_query_rules_alert" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location @@ -72,11 +73,16 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example" { custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Metric trigger example - query results grouped by metric; alert when results per metric_column cross threshold" + description = "Query results grouped into AggregatedValue; alert when results cross threshold" enabled = true - frequency = 5 - query = "requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by operation_Name, bin(timestamp, 5m)" + # Count all requests with server error result code grouped into 5-minute bins by HTTP operation + query = <<-QUERY + requests + | where tolong(resultCode) >= 500 + | summarize AggregatedValue = count() by operation_Name, bin(timestamp, 5m) +QUERY severity = 1 + frequency = 5 time_window = 30 trigger { operator = "GreaterThan" @@ -91,10 +97,6 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example" { } # Example: Alerting Action Cross-Resource -# Enables use of cross-resource queries to analyze query results across -# multiple Application Insights or Log Analytics resources. -# Alert if more than three HTTP requests returned a >= 500 result code -# in either of the Insights resources in the past 30 minutes. resource "azurerm_monitor_scheduled_query_rules_alert" "example2" { name = format("%s-queryrule2", var.prefix) location = azurerm_resource_group.example.location @@ -107,11 +109,19 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example2" { custom_webhook_payload = "{}" } data_source_id = azurerm_application_insights.example.id - description = "Scheduled query rule Alerting Action cross-resource example" + description = "Query may access data within multiple resources" enabled = true - frequency = 5 - query = format("let a=requests | where toint(resultCode) >= 500 | extend fail=1; let b=app('%s').requests | where toint(resultCode) >= 500 | extend fail=1; a | join b on fail", azurerm_application_insights.example2.id) + # Count requests in multiple log resources and group into 5-minute bins by HTTP operation + query = format(<<-QUERY + let a=requests + | where toint(resultCode) >= 500 + | extend fail=1; let b=app('%s').requests + | where toint(resultCode) >= 500 | extend fail=1; a + | join b on fail +QUERY +, azurerm_application_insights.example2.id) severity = 1 + frequency = 5 time_window = 30 trigger { operator = "GreaterThan" @@ -124,8 +134,8 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example2" { The following arguments are supported: -* `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `name` - (Required) The name of the scheduled query rule. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the scheduled query rule instance. * `data_source_id` - (Required) The resource URI over which log search query is to be run. * `frequency` - (Required) Frequency (in minutes) at which rule condition should be evaluated. Values must be between 5 and 1440 (inclusive). * `query` - (Required) Log search query. @@ -133,8 +143,8 @@ The following arguments are supported: * `trigger` - (Required) The condition that results in the alert rule being run. * `action` - (Required) An `action` block as defined below. * `authorized_resource_ids` - (Optional) List of Resource IDs referred into query. -* `description` - (Optional) The description of the Scheduled Query Rule. -* `enabled` - (Optional) Whether this Scheduled Query Rule is enabled. Default is `true`. +* `description` - (Optional) The description of the scheduled query rule. +* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. * `severity` - (Optional) Severity of the alert. Possible values include: 0, 1, 2, 3, or 4. * `throttling` - (Optional) Time (in minutes) for which Alerts should be throttled or suppressed. Values must be between 0 and 10000 (inclusive). @@ -167,7 +177,7 @@ The following arguments are supported: The following attributes are exported: -* `id` - The ID of the Scheduled Query Rule. +* `id` - The ID of the scheduled query rule. ## Import diff --git a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown index 20d2db6663e9..b8c14236804a 100644 --- a/website/docs/r/monitor_scheduled_query_rules_log.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_log.html.markdown @@ -3,12 +3,12 @@ subcategory: "Monitor" layout: "azurerm" page_title: "Azure Resource Manager: azurerm_monitor_scheduled_query_rules_log" description: |- - Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor + Manages a LogToMetricAction Scheduled Query Rules resources within Azure Monitor --- # azurerm_monitor_scheduled_query_rules_log -Manages a LogToMetricAction Scheduled Query Rule within Azure Monitor. +Manages a LogToMetricAction Scheduled Query Rules resource within Azure Monitor. ## Example Usage @@ -26,8 +26,7 @@ resource "azurerm_log_analytics_workspace" "example" { retention_in_days = 30 } -# Create Azure Monitor metric from log analytics data for -# the Computer named 'targetVM'. +# Example: LogToMetric Action for the named Computer resource "azurerm_scheduled_query_rule_log" "example" { name = format("%s-queryrule", var.prefix) location = azurerm_resource_group.example.location @@ -57,7 +56,7 @@ resource "azurerm_monitor_action_group" "example" { } } -# Create an alert on the new Scheduled Query Rules metric +# Example: Creates alert using the new Scheduled Query Rules metric resource "azurerm_monitor_metric_alert" "example" { name = "example-metricalert" resource_group_name = azurerm_resource_group.example.name @@ -84,12 +83,12 @@ resource "azurerm_monitor_metric_alert" "example" { The following arguments are supported: -* `name` - (Required) The name of the Scheduled Query Rule. Changing this forces a new resource to be created. -* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduled Query Rule instance. +* `name` - (Required) The name of the scheduled query rule. Changing this forces a new resource to be created. +* `resource_group_name` - (Required) The name of the resource group in which to create the scheduled query rule instance. * `criteria` - (Required) A `criteria` block as defined below. * `data_source_id` - (Required) The resource uri over which log search query is to be run. -* `description` - (Optional) The description of the Scheduled Query Rule. -* `enabled` - (Optional) Whether this Scheduled Query Rule is enabled. Default is `true`. +* `description` - (Optional) The description of the scheduled query rule. +* `enabled` - (Optional) Whether this scheduled query rule is enabled. Default is `true`. --- @@ -110,7 +109,7 @@ The following arguments are supported: The following attributes are exported: -* `id` - The ID of the Scheduled Query Rule. +* `id` - The ID of the scheduled query rule. ## Import From 0625b05fe27b613f431ab7d6504e874ba0dd1d14 Mon Sep 17 00:00:00 2001 From: David McPike <7037366+mcdafydd@users.noreply.github.com> Date: Tue, 3 Mar 2020 16:57:33 -0600 Subject: [PATCH 25/25] Fix markdown formatting --- ..._scheduled_query_rules_alert.html.markdown | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown index fc8b98559eb5..ef47304a5940 100644 --- a/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown +++ b/website/docs/r/monitor_scheduled_query_rules_alert.html.markdown @@ -47,14 +47,14 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example" { description = "Alert when total results cross threshold" enabled = true # Count all requests with server error result code grouped into 5-minute bins - query = <<-QUERY + query = <<-QUERY requests | where tolong(resultCode) >= 500 | summarize count() by bin(timestamp, 5m) QUERY - severity = 1 - frequency = 5 - time_window = 30 + severity = 1 + frequency = 5 + time_window = 30 trigger { operator = "GreaterThan" threshold = 3 @@ -76,14 +76,14 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example" { description = "Query results grouped into AggregatedValue; alert when results cross threshold" enabled = true # Count all requests with server error result code grouped into 5-minute bins by HTTP operation - query = <<-QUERY + query = <<-QUERY requests | where tolong(resultCode) >= 500 | summarize AggregatedValue = count() by operation_Name, bin(timestamp, 5m) QUERY - severity = 1 - frequency = 5 - time_window = 30 + severity = 1 + frequency = 5 + time_window = 30 trigger { operator = "GreaterThan" threshold = 3 @@ -112,17 +112,17 @@ resource "azurerm_monitor_scheduled_query_rules_alert" "example2" { description = "Query may access data within multiple resources" enabled = true # Count requests in multiple log resources and group into 5-minute bins by HTTP operation - query = format(<<-QUERY + query = format(<<-QUERY let a=requests | where toint(resultCode) >= 500 | extend fail=1; let b=app('%s').requests | where toint(resultCode) >= 500 | extend fail=1; a | join b on fail QUERY -, azurerm_application_insights.example2.id) - severity = 1 - frequency = 5 - time_window = 30 + , azurerm_application_insights.example2.id) + severity = 1 + frequency = 5 + time_window = 30 trigger { operator = "GreaterThan" threshold = 3