-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New Resource:
azurerm_monitor_scheduled_query_rules_alert
& `azurer…
…m_monitor_scheduled_query_rules_log` (#5053) * New Resource: `azurerm_monitor_scheduled_query_rules` * Acceptance tests passing * Fix linting errors; minor cleanup * 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 * Remove heredoc in docs example * fix response import * Update tests and docs to pass checks * Add moved tests to registration * First pass update docs post-review * First pass at separating into two resources * Rename action to alert in docs * Fix code review items * Fix lint issues and minor typos * Fix lint issues #2 * Fix lint issues #3 * Fix documentation error * Add monitor helpers * First pass address latest review * Validate metric_trigger query; add example to docs * Address review comments - Fix test crash - Move common functions to helpers - Add more schema validations - Add Update tests * Fix type assertions; simplify cross-resource query example * Review updates - Add metric alerts to LogToMetric tests and docs - Fix type assert from change to TypeList - Fix a couple typos * Add MaxItems for cross-resource query * 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 * Fix markdown formatting
- Loading branch information
Showing
16 changed files
with
2,512 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package monitor | ||
|
||
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{} { | ||
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 | ||
} | ||
return []interface{}{v} | ||
} | ||
|
||
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. | ||
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)) | ||
} | ||
|
||
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 | ||
} |
218 changes: 218 additions & 0 deletions
218
azurerm/internal/services/monitor/data_source_monitor_scheduled_query_rules_alert.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
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: dataSourceArmMonitorScheduledQueryRulesAlertRead, | ||
|
||
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, | ||
}, | ||
"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 dataSourceArmMonitorScheduledQueryRulesAlertRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*clients.Client).Monitor.ScheduledQueryRulesClient | ||
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
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("[DEBUG] Scheduled Query Rule %q was not found in Resource Group %q: %+v", name, resourceGroup, 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)) | ||
} | ||
|
||
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) | ||
} |
Oops, something went wrong.