Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azurerm_monitor_metric_alert_resource: keep using SingleResourceMultiMetricCriteria for legacy metric alerts #7995

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 105 additions & 22 deletions azurerm/internal/services/monitor/monitor_metric_alert_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,10 +399,26 @@ func resourceArmMonitorMetricAlertCreateUpdate(d *schema.ResourceData, meta inte
t := d.Get("tags").(map[string]interface{})
expandedTags := tags.Expand(t)

criteria, err := expandMonitorMetricAlertCriteria(d)
// The criteria type of "old" resource is `MetricAlertSingleResourceMultipleMetricCriteria` (rather than `MetricAlertMultipleResourceMultipleMetricCriteria`).
// We need to keep using that type in order to keep backward compatibility. Otherwise, changing the criteria type will cause error as reported in issue:
// https://github.com/terraform-providers/terraform-provider-azurerm/issues/7910
var isLegacy bool
if !d.IsNewResource() {
existing, err := client.Get(ctx, resourceGroup, name)
if err != nil {
return fmt.Errorf("retrieving Monitor Metric Alert %q (Resource Group %q): %+v", name, resourceGroup, err)
}
if existing.MetricAlertProperties == nil || existing.MetricAlertProperties.Criteria == nil {
return fmt.Errorf("unexpected nil properties of Monitor Metric Alert %q (Resource Group %q)", name, resourceGroup)
}
_, isLegacy = existing.MetricAlertProperties.Criteria.AsMetricAlertSingleResourceMultipleMetricCriteria()
}

criteria, err := expandMonitorMetricAlertCriteria(d, isLegacy)
if err != nil {
return fmt.Errorf(`Expanding criteria: %+v`, err)
}

parameters := insights.MetricAlertResource{
Location: utils.String(azure.NormalizeLocation("Global")),
MetricAlertProperties: &insights.MetricAlertProperties{
Expand Down Expand Up @@ -530,12 +546,15 @@ func resourceArmMonitorMetricAlertDelete(d *schema.ResourceData, meta interface{
return nil
}

func expandMonitorMetricAlertCriteria(d *schema.ResourceData) (insights.BasicMetricAlertCriteria, error) {
func expandMonitorMetricAlertCriteria(d *schema.ResourceData, isLegacy bool) (insights.BasicMetricAlertCriteria, error) {
switch {
case d.Get("criteria").(*schema.Set).Len() != 0:
return expandMonitorMetricAlertMetricCriteria(d.Get("criteria").(*schema.Set).List()), nil
if isLegacy {
return expandMonitorMetricAlertSingleResourceMultiMetricCriteria(d.Get("criteria").(*schema.Set).List()), nil
}
return expandMonitorMetricAlertMultiResourceMultiMetricForStaticMetricCriteria(d.Get("criteria").(*schema.Set).List()), nil
case d.Get("dynamic_criteria").(*schema.Set).Len() != 0:
return expandMonitorMetricAlertDynamicMetricCriteria(d.Get("dynamic_criteria").(*schema.Set).List()), nil
return expandMonitorMetricAlertMultiResourceMultiMetricForDynamicMetricCriteria(d.Get("dynamic_criteria").(*schema.Set).List()), nil
case len(d.Get("application_insights_web_test_location_availability_criteria").([]interface{})) != 0:
return expandMonitorMetricAlertWebtestLocAvailCriteria(d.Get("application_insights_web_test_location_availability_criteria").([]interface{})), nil
default:
Expand All @@ -544,11 +563,32 @@ func expandMonitorMetricAlertCriteria(d *schema.ResourceData) (insights.BasicMet
}
}

func expandMonitorMetricAlertMetricCriteria(input []interface{}) insights.BasicMetricAlertCriteria {
func expandMonitorMetricAlertSingleResourceMultiMetricCriteria(input []interface{}) insights.BasicMetricAlertCriteria {
criteria := make([]insights.MetricCriteria, 0)
for i, item := range input {
v := item.(map[string]interface{})
dimensions := expandMonitorMetricDimension(v["dimension"].([]interface{}))
criteria = append(criteria, insights.MetricCriteria{
Name: utils.String(fmt.Sprintf("Metric%d", i+1)),
MetricNamespace: utils.String(v["metric_namespace"].(string)),
MetricName: utils.String(v["metric_name"].(string)),
TimeAggregation: v["aggregation"].(string),
Dimensions: &dimensions,
Operator: insights.Operator(v["operator"].(string)),
Threshold: utils.Float(v["threshold"].(float64)),
})
}
return &insights.MetricAlertSingleResourceMultipleMetricCriteria{
AllOf: &criteria,
OdataType: insights.OdataTypeMicrosoftAzureMonitorSingleResourceMultipleMetricCriteria,
}
}

func expandMonitorMetricAlertMultiResourceMultiMetricForStaticMetricCriteria(input []interface{}) insights.BasicMetricAlertCriteria {
criteria := make([]insights.BasicMultiMetricCriteria, 0)
for i, item := range input {
v := item.(map[string]interface{})
dimensions := expandMonitorMetricAlertMultiMetricCriteriaDimension(v["dimension"].([]interface{}))
dimensions := expandMonitorMetricDimension(v["dimension"].([]interface{}))
criteria = append(criteria, insights.MetricCriteria{
Name: utils.String(fmt.Sprintf("Metric%d", i+1)),
MetricNamespace: utils.String(v["metric_namespace"].(string)),
Expand All @@ -564,11 +604,12 @@ func expandMonitorMetricAlertMetricCriteria(input []interface{}) insights.BasicM
OdataType: insights.OdataTypeMicrosoftAzureMonitorMultipleResourceMultipleMetricCriteria,
}
}
func expandMonitorMetricAlertDynamicMetricCriteria(input []interface{}) insights.BasicMetricAlertCriteria {

func expandMonitorMetricAlertMultiResourceMultiMetricForDynamicMetricCriteria(input []interface{}) insights.BasicMetricAlertCriteria {
criteria := make([]insights.BasicMultiMetricCriteria, 0)
for i, item := range input {
v := item.(map[string]interface{})
dimensions := expandMonitorMetricAlertMultiMetricCriteriaDimension(v["dimension"].([]interface{}))
dimensions := expandMonitorMetricDimension(v["dimension"].([]interface{}))
var ignoreDataBefore *date.Time
if v := v["ignore_data_before"].(string); v != "" {
// Guaranteed in schema validation func.
Expand Down Expand Up @@ -609,7 +650,7 @@ func expandMonitorMetricAlertWebtestLocAvailCriteria(input []interface{}) insigh
}
}

func expandMonitorMetricAlertMultiMetricCriteriaDimension(input []interface{}) []insights.MetricDimension {
func expandMonitorMetricDimension(input []interface{}) []insights.MetricDimension {
result := make([]insights.MetricDimension, 0)
for _, dimension := range input {
dVal := dimension.(map[string]interface{})
Expand Down Expand Up @@ -646,27 +687,69 @@ func expandMonitorMetricAlertAction(input []interface{}) *[]insights.MetricAlert
func flattenMonitorMetricAlertCriteria(input insights.BasicMetricAlertCriteria) []interface{} {
switch criteria := input.(type) {
case insights.MetricAlertSingleResourceMultipleMetricCriteria:
// As service is gonna deprecate data type of `MetricAlertSingleResourceMultipleMetricCriteria`,
// we use the same function to handle both single/multiple ResourceMultipleMetricCriteria cases.
// This is possible because their `AllOf` member implement the same interface: `MultiMetricCriteria`.
if criteria.AllOf == nil {
return nil
}
l := make([]insights.BasicMultiMetricCriteria, len(*criteria.AllOf))
for i, c := range *criteria.AllOf {
l[i] = c
}
return flattenMonitorMetricAlertMultiMetricCriteria(&l)
return flattenMonitorMetricAlertSingleResourceMultiMetricCriteria(criteria.AllOf)
case insights.MetricAlertMultipleResourceMultipleMetricCriteria:
return flattenMonitorMetricAlertMultiMetricCriteria(criteria.AllOf)
return flattenMonitorMetricAlertMultiResourceMultiMetricCriteria(criteria.AllOf)
case insights.WebtestLocationAvailabilityCriteria:
return flattenMonitorMetricAlertWebtestLocAvailCriteria(&criteria)
default:
return nil
}
}

func flattenMonitorMetricAlertMultiMetricCriteria(input *[]insights.BasicMultiMetricCriteria) []interface{} {
func flattenMonitorMetricAlertSingleResourceMultiMetricCriteria(input *[]insights.MetricCriteria) []interface{} {
if input == nil || len(*input) == 0 {
return nil
}
criteria := (*input)[0]

metricName := ""
if criteria.MetricName != nil {
metricName = *criteria.MetricName
}

metricNamespace := ""
if criteria.MetricNamespace != nil {
metricNamespace = *criteria.MetricNamespace
}

timeAggregation := criteria.TimeAggregation

dimResult := make([]map[string]interface{}, 0)
if criteria.Dimensions != nil {
for _, dimension := range *criteria.Dimensions {
dVal := make(map[string]interface{})
if dimension.Name != nil {
dVal["name"] = *dimension.Name
}
if dimension.Operator != nil {
dVal["operator"] = *dimension.Operator
}
dVal["values"] = utils.FlattenStringSlice(dimension.Values)
dimResult = append(dimResult, dVal)
}
}

operator := string(criteria.Operator)

threshold := 0.0
if criteria.Threshold != nil {
threshold = *criteria.Threshold
}

return []interface{}{
map[string]interface{}{
"metric_namespace": metricNamespace,
"metric_name": metricName,
"aggregation": timeAggregation,
"dimension": dimResult,
"operator": operator,
"threshold": threshold,
},
}
}

func flattenMonitorMetricAlertMultiResourceMultiMetricCriteria(input *[]insights.BasicMultiMetricCriteria) []interface{} {
if input == nil {
return nil
}
Expand Down