From 1ec27cc0b6d44503e0a92652f0954f801023deda Mon Sep 17 00:00:00 2001 From: Junyi Yi Date: Wed, 20 Jun 2018 17:28:07 -0700 Subject: [PATCH 01/15] Add new Action Group resource of Azure Monitor --- azurerm/config.go | 5 + azurerm/provider.go | 1 + azurerm/resource_arm_action_group.go | 320 +++++++++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 azurerm/resource_arm_action_group.go diff --git a/azurerm/config.go b/azurerm/config.go index fd23c447d24f..9cb3ab7577d5 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -147,6 +147,7 @@ type ArmClient struct { keyVaultManagementClient keyVault.BaseClient // Monitor + actionGroupsClient insights.ActionGroupsClient monitorAlertRulesClient insights.AlertRulesClient // Networking @@ -709,6 +710,10 @@ func (c *ArmClient) registerKeyVaultClients(endpoint, subscriptionId string, aut } func (c *ArmClient) registerMonitorClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) { + actionGroupsClient := insights.NewActionGroupsClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&actionGroupsClient.Client, auth) + c.actionGroupsClient = actionGroupsClient + arc := insights.NewAlertRulesClientWithBaseURI(endpoint, subscriptionId) setUserAgent(&arc.Client) arc.Authorizer = auth diff --git a/azurerm/provider.go b/azurerm/provider.go index d53daabbaf5a..96e79600f1e6 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -116,6 +116,7 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ + "azurerm_action_group": resourceArmActionGroup(), "azurerm_application_gateway": resourceArmApplicationGateway(), "azurerm_application_insights": resourceArmApplicationInsights(), "azurerm_application_security_group": resourceArmApplicationSecurityGroup(), diff --git a/azurerm/resource_arm_action_group.go b/azurerm/resource_arm_action_group.go new file mode 100644 index 000000000000..bc7c0b1b74e6 --- /dev/null +++ b/azurerm/resource_arm_action_group.go @@ -0,0 +1,320 @@ +package azurerm + +import ( + "fmt" + + "github.com/Azure/azure-sdk-for-go/services/monitor/mgmt/2018-03-01/insights" + "github.com/hashicorp/terraform/helper/schema" + "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, + }, + + "location": locationSchema(), + "resource_group_name": resourceGroupNameSchema(), + + "short_name": { + Type: schema.TypeString, + Required: true, + }, + + "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, + }, + "email_address": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + + "sms_receiver": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "country_code": { + Type: schema.TypeString, + Required: true, + }, + "phone_number": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + + "webhook_receiver": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "service_uri": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + + "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: utils.String(location), + ActionGroup: &insights.ActionGroup{ + GroupShortName: utils.String(shortName), + Enabled: utils.Bool(enabled), + EmailReceivers: expandActionGroupEmailReceiver(d), + SmsReceivers: expandActionGroupSmsReceiver(d), + WebhookReceivers: expandActionGroupWebHookReceiver(d), + }, + Tags: expandedTags, + } + + _, 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) + } + 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) + + 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) + } + 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(d *schema.ResourceData) *[]insights.EmailReceiver { + v, ok := d.GetOk("email_receiver") + if !ok { + return nil + } + + receivers := make([]insights.EmailReceiver, 0) + for _, receiverValue := range v.([]interface{}) { + 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 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 + + result = append(result, val) + } + } + return result +} + +func expandActionGroupSmsReceiver(d *schema.ResourceData) *[]insights.SmsReceiver { + v, ok := d.GetOk("sms_receiver") + if !ok { + return nil + } + + receivers := make([]insights.SmsReceiver, 0) + for _, receiverValue := range v.([]interface{}) { + 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 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 + + result = append(result, val) + } + } + return result +} + +func expandActionGroupWebHookReceiver(d *schema.ResourceData) *[]insights.WebhookReceiver { + v, ok := d.GetOk("webhook_receiver") + if !ok { + return nil + } + + receivers := make([]insights.WebhookReceiver, 0) + for _, receiverValue := range v.([]interface{}) { + 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 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 + + result = append(result, val) + } + } + return result +} From 4584f460d5d2539d1eedc830c7d64729a4cd8fb7 Mon Sep 17 00:00:00 2001 From: Junyi Yi Date: Thu, 21 Jun 2018 15:37:09 -0700 Subject: [PATCH 02/15] Add documentation of azurerm_action_group --- website/docs/r/action_group.html.markdown | 99 +++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 website/docs/r/action_group.html.markdown diff --git a/website/docs/r/action_group.html.markdown b/website/docs/r/action_group.html.markdown new file mode 100644 index 000000000000..ffb1bc525cbf --- /dev/null +++ b/website/docs/r/action_group.html.markdown @@ -0,0 +1,99 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_action_group" +sidebar_current: "docs-azurerm-resource-action-group" +description: |- + Manages an Action Group of Azure monitoring service + +--- + +# azurerm_action_group + +Manages an Action Group of Azure monitoring service. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "test" { + name = "monitoring-resources" + location = "West US" +} + +resource "azurerm_action_group" "test" { + name = "CriticalAlertsAction" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + short_name = "p0action" + + email_receiver { + name = "sendtoadmin" + email_address = "admin@contoso.com" + } + + email_receiver { + name = "sendtodevops" + email_address = "devops@contoso.com" + } + + sms_receiver { + name = "oncallmsg" + country_code = "1" + phone_number = "1231231234" + } + + webhook_receiver { + name = "callmyapiaswell" + service_uri = "http://example.com/alert" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Action Group. Changing this forces a new resource to be created. +* `location` - (Required) The location of this Action Group. +* `resource_group_name` - (Required) The name of the resource group in which to create the Action Group instance. +* `short_name` - (Required) The short name of the action group. This will be used in SMS messages. +* `enabled` - (Optional) Whether this action group is enabled. If an action group is not enabled, then none of its receivers will receive communications. Defaults to `true`. +* `email_receiver` - (Optional) The list of `email_receiver` blocks as defined below that are part of this action group. +* `sms_receiver` - (Optional) The list of `sms_receiver` blocks as defined below that are part of this action group. +* `webhook_receiver` - (Optional) The list of `webhook_receiver` blocks as defined below that are part of this action group. +* `tags` - (Optional) A mapping of tags to assign to the resource. + +--- + +`email_receiver` supports the following: + +* `name` - (Required) The name of the email receiver. Names must be unique (case-insensitive) across all receivers within an action group. +* `email_address` - (Required) The email address of this receiver. + +--- + +`sms_receiver` supports the following: + +* `name` - (Required) The name of the SMS receiver. Names must be unique (case-insensitive) across all receivers within an action group. +* `country_code` - (Required) The country code of the SMS receiver. +* `phone_number` - (Required) The phone number of the SMS receiver. + +--- + +`webhook_receiver` supports the following: + +* `name` - (Required) The name of the webhook receiver. Names must be unique (case-insensitive) across all receivers within an action group. +* `service_uri` - (Required) The URI where webhooks should be sent. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Route ID. + +## Import + +Action Groups can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_action_group.test /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Insights/actionGroups/myagname +``` From 24ed6acf8bd34afebfbef10e48ae27c77dbc08fa Mon Sep 17 00:00:00 2001 From: Junyi Yi Date: Thu, 21 Jun 2018 16:52:31 -0700 Subject: [PATCH 03/15] Fix location description in documentation. --- website/docs/r/action_group.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/action_group.html.markdown b/website/docs/r/action_group.html.markdown index ffb1bc525cbf..5a19c9396bfa 100644 --- a/website/docs/r/action_group.html.markdown +++ b/website/docs/r/action_group.html.markdown @@ -21,7 +21,7 @@ resource "azurerm_resource_group" "test" { resource "azurerm_action_group" "test" { name = "CriticalAlertsAction" - location = "${azurerm_resource_group.test.location}" + location = "Global" resource_group_name = "${azurerm_resource_group.test.name}" short_name = "p0action" @@ -53,7 +53,7 @@ resource "azurerm_action_group" "test" { The following arguments are supported: * `name` - (Required) The name of the Action Group. Changing this forces a new resource to be created. -* `location` - (Required) The location of this Action Group. +* `location` - (Required) The location of this Action Group. The only possible value is `Global`. * `resource_group_name` - (Required) The name of the resource group in which to create the Action Group instance. * `short_name` - (Required) The short name of the action group. This will be used in SMS messages. * `enabled` - (Optional) Whether this action group is enabled. If an action group is not enabled, then none of its receivers will receive communications. Defaults to `true`. From 3c89f4a3c676dae33e24ff29d00cacfdb16ea8e7 Mon Sep 17 00:00:00 2001 From: Junyi Yi Date: Thu, 21 Jun 2018 17:03:58 -0700 Subject: [PATCH 04/15] Add azurerm_action_group page to the ToC --- website/azurerm.erb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/azurerm.erb b/website/azurerm.erb index 5bfedaffc186..a8b56432e4a0 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -578,6 +578,10 @@ > Monitor Resources