-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
Introduce Action Group resource of Azure Monitor #1419
Changes from all commits
1ec27cc
4584f46
24ed6ac
3c89f4a
1f3eba2
d2f5e65
bc9e096
21e1183
589eb7e
463341e
e498d2d
f26338b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,313 @@ | ||
package azurerm | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2018-03-01/insights" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
"github.com/hashicorp/terraform/helper/validation" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func resourceArmActionGroup() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceArmActionGroupCreateOrUpdate, | ||
Read: resourceArmActionGroupRead, | ||
Update: resourceArmActionGroupCreateOrUpdate, | ||
Delete: resourceArmActionGroupDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
|
||
"location": locationSchema(), | ||
|
||
"resource_group_name": resourceGroupNameSchema(), | ||
|
||
"short_name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
|
||
"enabled": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: true, | ||
}, | ||
|
||
"email_receiver": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
"email_address": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"sms_receiver": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
"country_code": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
"phone_number": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"webhook_receiver": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
"service_uri": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.NoZeroValues, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"tags": tagsSchema(), | ||
}, | ||
} | ||
} | ||
|
||
func resourceArmActionGroupCreateOrUpdate(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).actionGroupsClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
name := d.Get("name").(string) | ||
location := azureRMNormalizeLocation(d.Get("location").(string)) | ||
resGroup := d.Get("resource_group_name").(string) | ||
|
||
shortName := d.Get("short_name").(string) | ||
enabled := d.Get("enabled").(bool) | ||
|
||
tags := d.Get("tags").(map[string]interface{}) | ||
expandedTags := expandTags(tags) | ||
|
||
parameters := insights.ActionGroupResource{ | ||
Location: &location, | ||
ActionGroup: &insights.ActionGroup{ | ||
GroupShortName: &shortName, | ||
Enabled: &enabled, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to @katbyte (@jeffreyCline could confirm that) , the new style is to use |
||
}, | ||
Tags: expandedTags, | ||
} | ||
|
||
if v, ok := d.GetOk("email_receiver"); ok { | ||
parameters.ActionGroup.EmailReceivers = expandActionGroupEmailReceiver(v.([]interface{})) | ||
} | ||
|
||
if v, ok := d.GetOk("sms_receiver"); ok { | ||
parameters.ActionGroup.SmsReceivers = expandActionGroupSmsReceiver(v.([]interface{})) | ||
} | ||
|
||
if v, ok := d.GetOk("webhook_receiver"); ok { | ||
parameters.ActionGroup.WebhookReceivers = expandActionGroupWebHookReceiver(v.([]interface{})) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. given these are lists we can just parse these out above and set these values all the time - since otherwise it's not possible to remove items from the lists e.g.
|
||
|
||
_, err := client.CreateOrUpdate(ctx, resGroup, name, parameters) | ||
if err != nil { | ||
return fmt.Errorf("Error creating or updating action group %s (resource group %s): %+v", name, resGroup, err) | ||
} | ||
|
||
read, err := client.Get(ctx, resGroup, name) | ||
if err != nil { | ||
return fmt.Errorf("Error getting action group %s (resource group %s) after creation: %+v", name, resGroup, err) | ||
} | ||
if read.ID == nil { | ||
return fmt.Errorf("Action group %s (resource group %s) ID is empty", name, resGroup) | ||
} | ||
|
||
d.SetId(*read.ID) | ||
|
||
return resourceArmActionGroupRead(d, meta) | ||
} | ||
|
||
func resourceArmActionGroupRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).actionGroupsClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
id, err := parseAzureResourceID(d.Id()) | ||
if err != nil { | ||
return fmt.Errorf("Error parsing action group resource ID \"%s\" during get: %+v", d.Id(), err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need to wrap this error message There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's my personal style. I don't think it really matters. |
||
} | ||
resGroup := id.ResourceGroup | ||
name := id.Path["actionGroups"] | ||
|
||
resp, err := client.Get(ctx, resGroup, name) | ||
if err != nil { | ||
if response.WasNotFound(resp.Response.Response) { | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("Error getting action group %s (resource group %s): %+v", name, resGroup, err) | ||
} | ||
|
||
d.Set("name", name) | ||
d.Set("resource_group_name", resGroup) | ||
if location := resp.Location; location != nil { | ||
d.Set("location", azureRMNormalizeLocation(*location)) | ||
} | ||
|
||
d.Set("short_name", *resp.GroupShortName) | ||
d.Set("enabled", *resp.Enabled) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need to de-pointer these; also we should be accessing these in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a shortcut in go instead of accessing |
||
|
||
if err = d.Set("email_receiver", flattenActionGroupEmailReceiver(resp.EmailReceivers)); err != nil { | ||
return fmt.Errorf("Error setting `email_receiver` of action group %s (resource group %s): %+v", name, resGroup, err) | ||
} | ||
|
||
if err = d.Set("sms_receiver", flattenActionGroupSmsReceiver(resp.SmsReceivers)); err != nil { | ||
return fmt.Errorf("Error setting `sms_receiver` of action group %s (resource group %s): %+v", name, resGroup, err) | ||
} | ||
|
||
if err = d.Set("webhook_receiver", flattenActionGroupWebHookReceiver(resp.WebhookReceivers)); err != nil { | ||
return fmt.Errorf("Error setting `webhook_receiver` of action group %s (resource group %s): %+v", name, resGroup, err) | ||
} | ||
|
||
flattenAndSetTags(d, resp.Tags) | ||
|
||
return nil | ||
} | ||
|
||
func resourceArmActionGroupDelete(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*ArmClient).actionGroupsClient | ||
ctx := meta.(*ArmClient).StopContext | ||
|
||
id, err := parseAzureResourceID(d.Id()) | ||
if err != nil { | ||
return fmt.Errorf("Error parsing action group resource ID \"%s\" during delete: %+v", d.Id(), err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't need to wrap this error message - so can we just return it directly? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Align with all other error messages in this code base would be a good style. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we consistently across the codebase don't wrap these error messages since they're an internal error users aren't going to be able to work around (vs a temporary issue in the Azure API in CRUD/Polling where they may be able to self-diagnose) - as such ID parsing error don't need wrapping. |
||
} | ||
resGroup := id.ResourceGroup | ||
name := id.Path["actionGroups"] | ||
|
||
resp, err := client.Delete(ctx, resGroup, name) | ||
if err != nil { | ||
if response.WasNotFound(resp.Response) { | ||
return nil | ||
} | ||
return fmt.Errorf("Error deleting action group %s (resource group %s): %+v", name, resGroup, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func expandActionGroupEmailReceiver(v []interface{}) *[]insights.EmailReceiver { | ||
receivers := make([]insights.EmailReceiver, 0) | ||
for _, receiverValue := range v { | ||
val := receiverValue.(map[string]interface{}) | ||
receiver := insights.EmailReceiver{ | ||
Name: utils.String(val["name"].(string)), | ||
EmailAddress: utils.String(val["email_address"].(string)), | ||
} | ||
receivers = append(receivers, receiver) | ||
} | ||
return &receivers | ||
} | ||
|
||
func expandActionGroupSmsReceiver(v []interface{}) *[]insights.SmsReceiver { | ||
receivers := make([]insights.SmsReceiver, 0) | ||
for _, receiverValue := range v { | ||
val := receiverValue.(map[string]interface{}) | ||
receiver := insights.SmsReceiver{ | ||
Name: utils.String(val["name"].(string)), | ||
CountryCode: utils.String(val["country_code"].(string)), | ||
PhoneNumber: utils.String(val["phone_number"].(string)), | ||
} | ||
receivers = append(receivers, receiver) | ||
} | ||
return &receivers | ||
} | ||
|
||
func expandActionGroupWebHookReceiver(v []interface{}) *[]insights.WebhookReceiver { | ||
receivers := make([]insights.WebhookReceiver, 0) | ||
for _, receiverValue := range v { | ||
val := receiverValue.(map[string]interface{}) | ||
receiver := insights.WebhookReceiver{ | ||
Name: utils.String(val["name"].(string)), | ||
ServiceURI: utils.String(val["service_uri"].(string)), | ||
} | ||
receivers = append(receivers, receiver) | ||
} | ||
return &receivers | ||
} | ||
|
||
func flattenActionGroupEmailReceiver(receivers *[]insights.EmailReceiver) []interface{} { | ||
result := make([]interface{}, 0) | ||
if receivers != nil { | ||
for _, receiver := range *receivers { | ||
val := make(map[string]interface{}, 0) | ||
val["name"] = *receiver.Name | ||
val["email_address"] = *receiver.EmailAddress | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's two potential crashes here - can we nil-check these? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Azure won't allow nil values for these fields. |
||
result = append(result, val) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
func flattenActionGroupSmsReceiver(receivers *[]insights.SmsReceiver) []interface{} { | ||
result := make([]interface{}, 0) | ||
if receivers != nil { | ||
for _, receiver := range *receivers { | ||
val := make(map[string]interface{}, 0) | ||
val["name"] = *receiver.Name | ||
val["country_code"] = *receiver.CountryCode | ||
val["phone_number"] = *receiver.PhoneNumber | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's three potential crashes here - can we nil-check these? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Azure won't allow nil values for these fields. |
||
result = append(result, val) | ||
} | ||
} | ||
return result | ||
} | ||
|
||
func flattenActionGroupWebHookReceiver(receivers *[]insights.WebhookReceiver) []interface{} { | ||
result := make([]interface{}, 0) | ||
if receivers != nil { | ||
for _, receiver := range *receivers { | ||
val := make(map[string]interface{}, 0) | ||
val["name"] = *receiver.Name | ||
val["service_uri"] = *receiver.ServiceURI | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's two potential crashes here - these should be nil-checked There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Azure won't allow nil values for these fields. |
||
result = append(result, val) | ||
} | ||
} | ||
return result | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a URI - so we can validate that it's either an Azure Resource URI (using
azure.ValidateResourceID
) or a URI in itselfThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We won't because Azure won't. We can pass anything to Azure. And if in the future Azure does, API call will return the error message.